博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java中primitive type的线程安全性
阅读量:7259 次
发布时间:2019-06-29

本文共 870 字,大约阅读时间需要 2 分钟。

Java中primite type,如char,integer,bool之类的,它们的读写操作都是atomic的,但是有几个例外:

  1. long和double类型不是atomic的,因为long和double都是8字节的,而在32位的CPU上,其机器字长为32位,操作8个字节需要多个指令操作。
  2. ++i或者i++,因为要先读后写,也是多步操作。

这些情况下,需要使用AutomicInteger,AutomicLong。

 

同时,java中的reference的读写也是automic的,虽然reference到底占几个字节没有明确定义,但至少以下可以保证:

  1. 在32位的CPU下,使用的是4字节的reference
  2. 在64位的CPU下,可以使用4字节或者8字节的reference

所以无论如何,对reference的操作肯定是单步操作,是automic的。

事实上,一个蛮有用的例子是cache switch - 你有两个cache pool,分别用两个reference指向:cache_in_build和cache_in_use,等cache_in_build完成了,你需要把cache_in_use指向它,没有问题,这是线程安全的。

但是问题是,jvm可以会reorder你的statement:

  1. cache_in_build.build()
  2. cache_in_use = cache_in_build

期望是cache在build完了之后,切换过去。

但是这两行代码并没有前后的dependency关系,所以JVM可以为了优化,进行乱序执行,变成:

  1. cache_in_use = cache_in_build
  2. cache_in_build.build()

于是,如果另一个线程在使用cache_in_use,在代码#1执行完之后,就访问到了正在build的那个cache,这是个问题。

解决方案是cache_in_use必须定义为volatile,保证happen-before的关系,拒绝乱序执行,从而保证其他线程看到的数据是有效的。

转载地址:http://ieodm.baihongyu.com/

你可能感兴趣的文章
iOS 自定义照片拍摄开发(GinCamera/GinPhotoCaptureManager)
查看>>
dubbo+zookeeper+springmvc+mybatis+redis
查看>>
JS基本数据类型和引用数据类型的区别
查看>>
在终端画画、炒股、玩游戏
查看>>
《大话数据结构》读后总结(一)
查看>>
纯JS实现走马灯
查看>>
真正的人工智能?Siri被曝将迎来革命性升级
查看>>
语音技术迎接人工智能变革时代
查看>>
JavaScript中Math对象常用方法总结
查看>>
Java中的"+"运算问题
查看>>
面试中程序员常见的Redis"刁难"问题,值得一读!
查看>>
api中文化之Rust-curl(上)
查看>>
设置垂直居中
查看>>
阿里云态势感知服务使用教程
查看>>
SOFARPC 5.5.X 新版发布 | 集成 Nacos 与 Hystrix
查看>>
深度解析双十一背后的阿里云 Redis 服务
查看>>
技术分享:树莓派配置篇
查看>>
巴曙松:收到了Roger送的BCH,已全捐给慈善基金
查看>>
Spring Cloud构建微服务架构:服务消费(基础)
查看>>
springcloud应用程序上下文层次结构
查看>>