一个多线程的小问题(对象同步)

2017-04-13  本文已影响0人  c7d122ec46c0

话不多,直接上代码,去年刚学java时发现的一个问题,现在看起来居然还懵了一会,所以记录下

public class TestSynconnized {
    private Object object = new Object();
    private volatile Integer i = 0;
    public void Add() {
        synchronized(i) {
            System.out.println("++i="+(++i)+Thread.currentThread().getName());
        }
    }    
    public static void main(String args[]) {
        TestSynconnized testSynconnized = new TestSynconnized();
        for (int i = 0; i < 20; i++) {

            Thread thread = new Thread(new Runnable() {
                public void run() {
                    for (int i = 0; i < 1000; i++) {
                        testSynconnized.Add();    
                    }
                }
            });

            thread.start();
        }
        while (Thread.activeCount() > 1) {
            Thread.yield();
        }

        System.out.println(testSynconnized.i);    
    }
}

运行这段代码发现并不是每次执行的结果都是20000,原因:在同步方法块中更新了锁对象,导致锁失效。
在执行i++并退出同步方法块后,另一个持有原先的i对象锁的线程进入同步方法块。此时下一个线程运行到synchronized时锁条件已经变化,也可进入同步方法块,再次感谢知乎网友meantobe的解答,直接复制了答案

修改方法

public class TestSynconnized {

    private Object object = new Object();
    private volatile Integer i = 0;
    public synchronized void Add() {
        {
            System.out.println("++i="+(++i)+Thread.currentThread().getName());
        }
    }
    public static void main(String args[]) {
        TestSynconnized testSynconnized = new TestSynconnized();
        for (int i = 0; i < 20; i++) {

            Thread thread = new Thread(()-> {
                    for (int j = 0; j < 1000; j++) {
                        testSynconnized.Add();
                    }
                }
            );

            thread.start();
        }
        while (Thread.activeCount() > 1) {
            Thread.yield();
        }

        System.out.println(testSynconnized.i);
    }

}

这段代码实际是从深入理解java虚拟机里面捞出来改的

上一篇下一篇

猜你喜欢

热点阅读