volatile详解

           volatile作为一个轻量级锁机制,首先保证了可见性,处理器使用MESI(修改、独占、共享、无效)缓存一致性协议来保证可见性,当多个线程修改数据时,先到达的会使用Lock前缀指令锁住主缓存的缓存行,缓存行就是我们数据存在缓存里的最小单位,修改自己的数据之后,其它线程通过嗅探技术发现主存的数据修改,会无效化自己的缓存,使得下次取数据的时候从主存里取数据

 注意两点:
一:happens-before原则:假如一写一读两个线程同时操作数据,写优先
二:两个线程同时写会有伪共享问题

伪共享问题:

        当两个线程同时修改同一个缓存行的数据的时候,因为先到达会锁住缓存行,那么第二个到达的依旧会等待,类似于synchronized悲观锁,比如线程A修改缓存行的A数据,线程B修改同一个缓存行的B数据,就会变成串行修改,也就是伪共享问题

怎么解决?

        当下采用的多是使不同变量在不同缓存行,即如果数据占不了一个缓存行,那么填充缓存行,把缓存行填满,使不同的数据不再同一个缓存行中,比如@Contended注解,concurrentHashMap就是这样用的,还有Disruptor框架采用填充缓存行的方式,有兴趣的可以去了解下

不保证原子性

        对于i++操作,这个i++是分为了三步骤,取值、加、设值,当线程A取得主存的值i=10,线程B取得值为10,线程A加1,设置回主存,线程B也加1,设置回主存,两个线程加完之后,数据依旧为1,所以不保证原子性

特别注意:

        很多人对这个可见性有所疑惑,认为线程B修改到主存之后,就会让线程A知道,线程A重新去取值,注意这里并不是,线程A已经取过值之后,其它值修改了主存,他不会去取值,而是自己进行加的操作,这也就是没有原子性的原因,如果线程A会去重新取值的话,那么以新的值来操作,不就是有原子性了吗

        volatile的第二个作用是插入内存屏障禁止指令重排序,虽然保证了一些数据安全,但是效率变低

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

推荐阅读更多精彩内容

  • 对于volatile这个关键字,相信很多朋友都听说过,甚至使用过,这个关键字虽然字面上理解起来比较简单,但是要用好...
    柳蒿阅读 218评论 0 1
  • 如未作特殊说明,文章均为原创,转发请注明出处。 [TOC] 前提: 在Windows系统下如何编译hsdis-am...
    小安的大情调阅读 2,840评论 0 3
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,161评论 1 32
  • 专业考题类型管理运行工作负责人一般作业考题内容选项A选项B选项C选项D选项E选项F正确答案 变电单选GYSZ本规程...
    小白兔去钓鱼阅读 9,072评论 0 13
  • 一、volatile简介 在单线程环境中,我们几乎用不到这个关键词,但是多线程环境中,这个关键词随处可见。而且也是...
    贪挽懒月阅读 6,187评论 4 16