zoukankan      html  css  js  c++  java
  • Java中primitive type的线程安全性

    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的关系,拒绝乱序执行,从而保证其他线程看到的数据是有效的。

  • 相关阅读:
    进程 触发器
    关于 if条件 光标 循环的综合应用
    3-15记录
    day3.python 学习之列表
    day2: python3.5学习——逻辑判断
    day1: python3.5学习
    OpenGL_曲线函数
    OpenGL_赛平斯基垫片
    【quick-cocos2d-x 游戏开发之一】开发工具sublime text及其强力插件QuickXDev
    Python正则表达式指南
  • 原文地址:https://www.cnblogs.com/baiyanhuang/p/3837194.html
Copyright © 2011-2022 走看看