关于对网上一则java synchronized 线程同步的分析

为了看一些synchronized相关的内容,查了网上的一些例子,然后糊涂了一个下午,最终搞懂了,作者可能是好心,但是感觉分析的不彻底,给看的人也容易造成困惑,把我的分析过程贴出来,本来代码比较乱,但分析的过程中收获了一些东西

网址如下:http://blog.csdn.net/hello_chillax/article/details/44992771

我的代码  稍微修改了下

package com.testSync;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by CHENYUAN797 on 2017-06-13.
 */
public class JavaThread implements Runnable {

//    wait annotation--------------

//    Causes the current thread to wait until another thread invokes the java.lang.Object.notify() method
//    or the java.lang.Object.notifyAll() method for this object.
//    In other words, this method behaves exactly as if it simply performs the call wait(0).

//    The current thread must own this object's monitor.
//    The thread releases ownership of this monitor and waits until
//    another thread notifies threads waiting on this object's monitor to wake up either
//    through a call to the notify method or the notifyAll method.

//    synchronized (obj) {
//        while (<condition does not hold>)
//        obj.wait();
//        ... // Perform action appropriate to condition
//    }

//    This method should only be called by a thread that is the owner of this object's monitor.
//    See the notify method for a description of the ways in which a thread can become the owner of a monitor.

//    notify annotation------------

//    Wakes up a single thread that is waiting on this object's monitor.
//    If any threads are waiting on this object, one of them is chosen to be awakened.
//    A thread waits on an object's monitor by calling one of the wait methods.

//    Only one thread at a time can own an object's monitor.


    private String name;
    private Object prev;
    private Object self;

    private JavaThread(String name, Object prev, Object self) {
        this.name = name;
        this.prev = prev;
        this.self = self;
    }
    @Override
    public void run() {
        int count = 3;
        while (count > 0) {
            synchronized (prev) {
                synchronized (self) {
                    System.out.println(name);
                    count--;
                    self.notify();
                    Thread t=Thread.currentThread();
                    System.out.println(self+"notify-"+getStringDate()+"-"+t.getName());
                }
                try {
                    Thread t=Thread.currentThread();
                    System.out.println(prev+"wait-"+getStringDate()+"-"+t.getName());
                    prev.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public String getStringDate() {
        Date currentTime = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
        String dateString = formatter.format(currentTime);
        return dateString;
    }

    public static void main(String[] args) throws Exception {
        Object a = "aaaa";
        Object b = "bbbb";
        Object c = "cccc";
        JavaThread pa = new JavaThread("A", c, a);
        JavaThread pb = new JavaThread("B", a, b);
        JavaThread pc = new JavaThread("C", b, c);
        new Thread(pa).start();
        Thread.sleep(2000);
        new Thread(pb).start();
        Thread.sleep(2000);
        new Thread(pc).start();
    }
}
执行结果及分析如下:
 
 

A

aaaanotify-16:18:07-Thread-0

ccccwait-16:18:07-Thread-0

B

bbbbnotify-16:18:09-Thread-1

aaaawait-16:18:09-Thread-1

C

ccccnotify-16:18:11-Thread-2      激活ccccwait-16:18:07-Thread-0同时进入线程1

A                                                               打印A

bbbbwait-16:18:11-Thread-2           同上面的ccccnotify-16:18:11-Thread-2在同一代码块内执行

aaaanotify-16:18:11-Thread-0         打印A 在同一代码块同时激活aaaawait-16:18:09-Thread-1

                                                                 因为这段在线程0内执行,所以ccccwait-16:18:11-Thread-0

                                                                 这一段理所当然要执行,又因为激活了a所以B要执行

B

ccccwait-16:18:11-Thread-0

bbbbnotify-16:18:11-Thread-1         这一段又激活了bbbbwait-16:18:11-Thread-2,然后继续执行Thread2里面的代码所以有下面的三段,如此往下推…

C

aaaawait-16:18:11-Thread-1

ccccnotify-16:18:11-Thread-2

A

bbbbwait-16:18:11-Thread-2

aaaanotify-16:18:11-Thread-0

B

ccccwait-16:18:11-Thread-0

bbbbnotify-16:18:11-Thread-1         这一段为什么看起来顺序有点不同,其实上面的notify 每个下面的三行都是并列运行的,毕竟是不同线程,

而且线程里也没有涉及耗时操作,所以乱序正常

C

ccccnotify-16:18:11-Thread-2

aaaawait-16:18:11-Thread-1 

bbbbwait-16:18:11-Thread-2                     这个程序的缺点,虽然调来调去,结果留下了一个永远关不上的线程在wait,程序其实没有结束

 
 
 
 
总结一下 这个示例就是把lock嵌套,希望通过连续冻结解冻来示意线程锁的机制,但其实最终线程有一个wait方法一直没有收到notify信号,程序没有关掉,举个例子,有个
客栈,有n间房,作者希望的是这n间房子里的人不停的与第n-1个人替换房间,但是第一个房子永远空着,第n个人永远没有房子,程序永远不能结束,永远敞开着。。。
 
 
 
 
作者的简化版如下:
 
 
 
 
package com.testSync;

import javax.swing.*;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by CHENYUAN797 on 2017-06-13.
 */
public class TestTwoLock implements Runnable {
    private  String LOCK;
    private  String LOCK1;

    public TestTwoLock(String LOCK, String LOCK1) {
        this.LOCK = LOCK;
        this.LOCK1 = LOCK1;
    }

    public static void main(String[] args) {
        Thread t = new Thread(new TestTwoLock("AAA","BBB"));
        t.start();

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        Thread t1 = new Thread(new TestTwoLock("BBB","AAA"));
        t1.start();

        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void run() {
        synchronized (LOCK) {
            synchronized (LOCK1) {
                LOCK1.notify();
                System.out.println(LOCK1+" notify--"+getStringDate());

            }
            try {
                LOCK.wait();
                System.out.println(LOCK+" wait--"+getStringDate());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static String getStringDate() {
        Date currentTime = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
        String dateString = formatter.format(currentTime);
        return dateString;
    }
}
结果如下:
BBB notify--16:40:42
AAA notify--16:40:44
AAA wait--16:40:44
 
 
这个容易懂一点 ,但是我有个疑问,这种synchronized代码块嵌套synchronized代码块在什么情况下用?都是一个线程,多级同步?互解锁?
tips:java 在debug机制下是单线程的,所以涉及到多线程的东西,最好打好log,走debug的话,你不知道进的是哪个线程。。。。

猜你喜欢

转载自blog.csdn.net/xiaoe3504xiaoe/article/details/73188411
今日推荐