synchronized Interger失败

原因:Synchronized锁的是对象,也就是identityHashCode所指向的内存地址中的对象实例(根据对象内存地址生成散列值)
下面先看一个demo

static public class MyRunable implements Runnable{
        private Integer ncount = 0;
        public void run() {
            Integer temp = 0;
            //System.out.println("thread id:"+Thread.currentThread().getId()+"count"+ncount+" identityHashCode:"+System.identityHashCode(ncount)+" HashCode:"+ncount.hashCode());
            while (temp <= 100){
                synchronized (ncount){
                    ncount++;
                    temp = ncount;
                    //System.out.println("thread id:"+Thread.currentThread().getId()+"count"+ncount+" identityHashCode:"+System.identityHashCode(ncount)+" HashCode:"+ncount.hashCode());
                    System.out.println("thread id:"+Thread.currentThread().getId()+"count:"+ncount);
                }
                try {
                    Thread.sleep(1000000000);
                }
                catch (Exception e){
                    e.printStackTrace();
                }

            }

        }
    }

 public static void main(String [] args) throws Exception{
        Runnable runnable = new MyRunable();
        Thread thread1 = new Thread(runnable);
        Thread thread2 = new Thread(runnable);
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
    }

结果输出(如果结果不一致多运行几次):
在这里插入图片描述
发现结果和我们期望不一样,count的值没被锁住。这是为什么呢?难道是成员变量的原因?我们将ncount修改成static

 static private Integer ncount = 0;

结果依旧一样,难道是Integer 类型的问题?,那我们尝试使用类试试

static public class CA{

    }

static public class MyRunable implements Runnable{
	private CA lock = new CA();
	...
	//synchronized (ncount)
	synchronized (lock){
	...
	}
}

在这里插入图片描述

发现替换成类之后结果就符合预期。那么synchronized Interger为什么会失败呢?看一下线程调用堆栈
在这里插入图片描述
上图中,每一个线程锁住的资源其实都并非是同一个,这就可以解释为什么对Integer类型进行加锁仍然是非线程安全的。其实Synchronized锁的是对象,也就是identityHashCode所指向的内存地址中的对象实例(根据对象内存地址生成散列值)既然Synchronized是根据identityHashCode 所指向的内存地址中的对象实例来锁的,那么说明Integer的identityHashCode是发生了变化的,而CA是固定的。下面看日志:
在这里插入图片描述
在这里插入图片描述
最后总结下,synchronized(Integer)时,当值发生改变时,基本上每次锁住的都是不同的对象实例,想要保证线程安全,推荐使用AtomicInteger之类会更靠谱。

参考博客:
https://www.iteye.com/blog/gao-xianglong-2396071

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值