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

话不多,直接上代码,去年刚学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虚拟机里面捞出来改的

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Java多线程学习 [-] 一扩展javalangThread类 二实现javalangRunnable接口 三T...
    影驰阅读 3,022评论 1 18
  • 本文主要讲了java中多线程的使用方法、线程同步、线程数据传递、线程状态及相应的一些线程函数用法、概述等。 首先讲...
    李欣阳阅读 2,527评论 1 15
  • 该文章转自:http://blog.csdn.net/evankaka/article/details/44153...
    加来依蓝阅读 7,400评论 3 87
  • 写在前面的话: 这篇博客是我从这里“转载”的,为什么转载两个字加“”呢?因为这绝不是简单的复制粘贴,我花了五六个小...
    SmartSean阅读 4,828评论 12 45
  • 少女第二天。 少女们在一天枯燥的排练中终有一日会化茧成蝶,那我们这些工作人员在他们排练的时候也玩手机闲话家常工作到...
    歩亦寒阅读 135评论 0 0