synchronized 加锁Integer对象(数据重复)详解
场景描述:多线程输出1到100,对静态Integer对象加锁,synchronized代码块中操作Integer对象,发生线程安全问题(数据重复)
代码:
public class MyRunnableTest implements Runnable {
public static Integer i = new Integer(0);
@Override
public void run() {
while(true){
synchronized (i) {
if(i<100){
i++;
System.out.println(Thread.currentThread()+"i = " + i);
}else {
break;
}
}
}
}
public static void main(String[] args) {
Thread t1 = new Thread(new MyRunnableTest());
Thread t2 = new Thread(new MyRunnableTest());
t1.start();
t2.start();
}
}
运行结果:
Thread[Thread-0,5,main]i = 1
Thread[Thread-1,5,main]i = 3
Thread[Thread-1,5,main]i = 4
Thread[Thread-1,5,main]i = 5
Thread[Thread-1,5,main]i = 6
Thread[Thread-0,5,main]i = 5
Thread[Thread-1,5,main]i = 7
Thread[Thread-0,5,main]i = 8
Thread[Thread-1,5,main]i = 9
Thread[Thread-0,5,main]i = 10
Thread[Thread-1,5,main]i = 11
Thread[Thread-0,5,main]i = 12
Thread[Thread-1,5,main]i = 13
从运行结果中可以发现发生了线程安全问题,为什么呢?为什么synchronized无效了。
我的排查思路:
1、因为没有进行任何的额外操作,所以首先定位问题在i++处
通过javap分析字节码命令,总结:

可以看出:i++的实际操作为:Integer.valueOf(Integer.intValue(i)+1)
我们在看看Integer中vauleOf的源码:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
cache[]数组初始化:
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
其中low为-128,hight为127。可以了解到,当i的值为-128~127时,是从IntegerCache中取的(可以理解为从缓存中取的),超过部分是new出来的对象。
2、目前我们慢慢开始解开了问题的面纱,每当i发生自增后,所对象改变了,这里我们还需要清楚一下,synchronized在锁对象发生改变时(测试发现,引用类型对象的内在属性变化不会释放锁)会立即释放锁。所以这里就会出现线程安全问题,而且在单核的运行环境下,所有的线程是并发执行而不是并行执行,当我们运行到system.out.println时,锁已经释放了,假如这边t1线程(当前运行的线程,i=1的情况)释放CPU资源,t2执行,这时i等于2(i++之前),当执行到system.out.println时释放cpu资源(此时i=3),t1执行,i此时已经为3了,所以输出3,在释放cpu资源,t2执行,输出3,这时出现了输出重复值的情况。
synchronized 加锁Integer对象(数据重复)详解的更多相关文章
- ContentProvider数据访问详解
ContentProvider数据访问详解 Android官方指出的数据存储方式总共有五种:Shared Preferences.网络存储.文件存储.外储存储.SQLite,这些存储方式一般都只是在一 ...
- 【转载】图说C++对象模型:对象内存布局详解
原文: 图说C++对象模型:对象内存布局详解 正文 回到顶部 0.前言 文章较长,而且内容相对来说比较枯燥,希望对C++对象的内存布局.虚表指针.虚基类指针等有深入了解的朋友可以慢慢看.本文的结论都在 ...
- Scala 深入浅出实战经典 第64讲:Scala中隐式对象代码实战详解
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- 【HANA系列】SAP HANA XS使用JavaScript数据交互详解
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA XS使用Jav ...
- JVM 运行时数据区详解
一.运行时数据区 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同数据区域. 1.有一些是随虚拟机的启动而创建,随虚拟机的退出而销毁,所有的线程共享这些数据区. 2.第二种则 ...
- 【HANA系列】【第一篇】SAP HANA XS使用JavaScript数据交互详解
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列][第一篇]SAP HANA XS ...
- CEPH-4:ceph RadowGW对象存储功能详解
ceph RadosGW对象存储使用详解 一个完整的ceph集群,可以提供块存储.文件系统和对象存储. 本节主要介绍对象存储RadosGw功能如何灵活的使用,集群背景: $ ceph -s clust ...
- Jquery遍历筛选数组的几种方法和遍历解析json对象|Map()方法详解
Jquery遍历筛选数组的几种方法和遍历解析json对象|Map()方法详解 一.Jquery遍历筛选数组 1.jquery grep()筛选遍历数组 $().ready( function(){ v ...
- java使用POI操作XWPFDocument中的XWPFRun(文本)对象的属性详解
java使用POI操作XWPFDocument中的XWPFRun(文本)对象的属性详解 我用的是office word 2016版 XWPFRun是XWPFDocument中的一段文本对象(就是一段文 ...
随机推荐
- 初试Gevent – 高性能的Python并发框架
Gevent是一个基于greenlet的Python的并发框架,以微线程greenlet为核心,使用了epoll事件监听机制以及诸多其他优化而变得高效. 于greenlet.eventlet相比,性能 ...
- 到底什么是BFC、IFC、GFC和FFC,次奥?
软件开发的一般被称为民工,搞前端的,有人形容为是掏粪工,说白了连民工级别高都没有.说直接点就是个制作界面的,注意,连设计界面的都算不上,一般前端都是拿着设计稿去照这样子开发的. 说这些无非是觉得前端前 ...
- HDU 5862 Counting Intersections 扫描线+树状数组
题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=5862 Counting Intersections Time Limit: 12000/ ...
- Qt动态连接库/静态连接库创建与使用,QLibrary动态加载库
版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:Qt动态连接库/静态连接库创建与使用,QLibrary动态加载库 本文地址:https ...
- Linux架设DDNS服务器之自动更新脚本
问题描述:客户端是动态IP,每次连网之后要nsupdate下才可以把客户端的hostname 与IP映射更新到DNS Server上 命令如下: nsupdate -k K*****.key > ...
- php缩略图
/*引入文件Easyphpthumbnail.class.php 引用地址:http://www.itdaodan.com/article-detail-id-252.html */ class ...
- django里的http协议
一个普通的user Begin########## ['__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__' ...
- 解决Lenovo(ldeapad)笔记本F1-F12功能键操作无效的问题
1.操作条件:Lenovo笔记本自带的“一键恢复”按钮 2.操作方法:上下键为切换选项,回车键(Enter)为确定选择 (1)在笔记本电脑关机状态下,使用曲别针或其他物件按下笔记本自带的“一键恢复按钮 ...
- List、Set、Map典型实现
1:集合 Collection(单列集合) List(有序,可重复) ArrayList 底层数据结构是数组,查询快,增删慢 线程不安全,效率高 Vector 底层数据结构是数组,查询快,增删慢 线程 ...
- MVC4中control的增删改查
public class TestController : Controller { private LeaveEntities db = new LeaveEntities(); // // GET ...