你竟然用Integer作为synchronized的锁对象?
2020-03-24 16:23:23来源:博客园 阅读 ()
你竟然用Integer作为synchronized的锁对象?
在使用多线程编程时,往往会使用一些手段保证线程安全,也就是加锁,但是加锁也必须合理,如使用synchronized对对象加锁时,如果不注意,还可能发生错误的加锁。
先看一段小测试,在这个小测试中,启动了1000个线程,每个线程在对integer加1前都先获得integer的锁,这看似是线程安全的,并且预期可能会得到1000这个值,而然并不然,在运行多次之后他总是输出<=1000的值,那么,这犊子是哪出问题了。
static Integer integer =new Integer("0");
static CountDownLatch mCountDownLatch =new CountDownLatch(1000);
public static void main(String[] args) throws InterruptedException {
for (int i = 1; i <=1000; i++) {
new Thread(()->{
synchronized (integer){
integer++;
mCountDownLatch.countDown();
}
}).start();
}
mCountDownLatch.await();
System.out.println(integer);
}
这其实就是上述所说:"错误的加锁对象",也就是Integer作为锁对象这是个不正确的选择。
那在说Integer,不少人可能会见过这样的题。
Integer i1 =125;
Integer i2 =125;
System.out.println(i1==i2);
Integer i3 =135;
Integer i4 =135;
System.out.println(i3==i4);
答案是true,false,这样的结果是由Integer的缓存导致,在直接对Integer=xxx时候,其实调用了Integer.valueOf,(可以使用javap命令反编译查看)
而Integer.valueOf中,如果参数值在一定范围内,就从IntegerCache缓存中返回,也就是说在一定范围内多个相同的值是同一个对象,超出的话则return new Integer(i)返回一个新的Integer。而这个范围在-128-127,
在上面的135显然不在范围,则返回的是新对象,又由于==是比较内存地址,所以上述会出现false。如果要比较包装类是否相等,正确的做法是equals方法,Integer也重写了equals,判断内部基本数据类型是否一样。
这样一来,synchronized(integer)原因就知道了, integer++是创建了一个新的Integer对象,并将引用赋值给integer。因为integer一直在变,线程每次加锁可能都加在了不同对象的实例上,导致临界区控制出现问题。
解决办法也很容易,只要加在一个不变的对象上即可。
static Integer integer =new Integer("0");
static CountDownLatch mCountDownLatch =new CountDownLatch(1000);
static Object sObject= new Object();
public static void main(String[] args) throws InterruptedException {
for (int i = 1; i <=1000; i++) {
new Thread(()->{
synchronized (sObject){
integer++;
mCountDownLatch.countDown();
}
}).start();
}
mCountDownLatch.await();
System.out.println(integer);
}
(不只Integer,Character、Short、Long也有缓存,但是Float和Double却没有)
原文链接:https://www.cnblogs.com/HouXinLin/p/12560047.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- 作为一个面试官,我想问问你Redis分布式锁怎么搞? 2020-06-10
- 天哪!手动编写mybatis雏形竟然这么简单 2020-06-06
- 第六章第三十七题(格式化整数)(Format an integer) - 编程 2020-05-26
- 我的奇葩面试经历:HR竟然主动提价,比预期高5K,我一脸懵逼 2020-05-25
- 技术大佬:我去,你竟然还不会用 this 关键字 2020-05-24
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash