最新公告
  • 欢迎您光临波比源码,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入我们
  • Java并发编程的艺术(三)——volatile

    1. 并发编程的两个关键问题

    并发是让多个线程同时履行,若线程之间是独立的,那并发实现起来很简单,各自履行各自的就行;但常常多条线程之间需要同享数据,此时在并发编程进程中就不可避免要斟酌两个问题:通讯 与 同步。

    • 通讯
      通讯是指消息在两条线程之间传递。
      既然要传递消息,那接收线程 和 发送线程之间必须要有个前后关系,此时就需要用到同步。通讯和同步是相辅相成的。

    • 同步
      同步是指,控制多条线程之间的履行次序。

    2. 通讯的方式

    2.1 通讯方式的种类

    线程之间的通讯1共有两种方式:同享内存 和 消息传递。

    • 同享内存
      同享内存指的是多条线程同享同1片内存,发送者将消息写入内存,接收者从内存中读取消息,从而实现了消息的传递。
      但这类方式有个弊端,即需要程序员来控制线程的同步,即线程的履行次序。

    这类方式并没有真正地实现消息传递,只是从结果上来看就像是将消息从1条线程传递到了另外一条线程。

    • 消息传递
      顾名思义,消息传递指的是发送线程直接将消息传递给接收线程。
      由于履行次序由并发机制完成,因此不需要程序员添加额外的同步机制,但需要声明消息发送和接收的代码。

    综上所述:对同享内存的通讯方式,需要进行显示的同步,隐式的通讯;
    而对消息传递的通讯方式,需要隐式的同步,显示的通讯。

    2.2 Java使用的通讯方式

    Java使用同享内存的方式实现多线程之间的消息传递。因此,程序员需要写额外的代码用于线程之间的同步。

    PS:其实同享内存的方式从实现进程来看,跟消息传递1点关系都没有:1条线程将消息存入同享内存,另外一条线程从同享内存中读这条消息。
    但从结果来看,全部进程就好像是1条消息被从线程A传递到了线程B。
    这类方式之所以能实现消息传递,依托于两点:

    • 必须有1片同享的内存
    • 必须要实现多线程的同步

    3. Java多线程的内存模型(简化版)

    所有线程都同享1片内存,用于存储同享变量;
    另外,每条线程都有各自的存储空间,存储各自的局部变量、方法参数、异常对象。

    4. volatile是甚么?

    Java采取同享内存的方式实现消息传递,而同享内存需要依托于同步。Java提供了synchronized、volatile关键字实现同步。另外volatile关键字还具有1些额外的功能。

    5. volatile的使用

    在成员变量前加上该关键字便可。

    public volatile boolean flag;

    6. volatile的特性

    6.1 重排序

    重排序是计算机为了提高程序履行效力而对代码的履行顺序进行调剂。你以为代码是1行行顺序履行的,但实际并不是如此,重排序详解请移步至:Java并发编程的艺术(2)——重排序

    若两行指令之间没有依赖关系,那末计算机可以对他们的顺序进行重排序,但如果两行之间的某个变量被volatile修饰后,重排序规则会产生变化。

    在以下情况下,即便两行代码之间没有依赖关系,也不会产生重排序:

    • volatile读

      • 若volatile读操作的前1行动volatile读/写,则这两行不会产生重排序
      • volatile读操作和它后1行代码都不会产生重排序
    • volatile写

      • volatile写操作和它前1行代码都不会产生重排序;
      • 若volatile写操作的后1行代码为volatile读/写,则这两行不会产生重排序。

    6.2 可见性

    甚么是内存可见性?

    “内存可见性”指的是1条线程修改完1个同享变量后,另外一个线程若访问这个变量将会访问到修改后的值。即:1条线程对同享变量的修改,对其他线程立便可见。

    但如果未对同享变量采取同步机制,那末同享变量的修改不会对其他线程立便可见。

    为何会出现内存不可见的情况?

    通过上文可知,在Java中每条线程都有各自独立的存储空间,另外还有1个所有线程同享的内存空间。
    当开启线程时,系统会将同享内存中的所有同享变量拷贝1份到线程专属的存储空间中。接下来该线程在结束前的所有操作都是基于自己的存储空间进行的。因此,若1条线程改变了1个同享变量,仅仅改变的是这条线程专属存储空间中的变量值;此时若其他线程访问这个变量,访问的依然是先前从同享存储空间读出来的值。
    但是我们希望1条线程将某个同享变量修改后,其他线程能立即访问到这个最新的值,而不是失效值。
    这时候就需要同步机制来解决这个问题。

    如何确保同享变量的可见性?

    要确保所有同享变量对所有线程是可见的,就需要给所有同享变量使用同步。在Java中你可以选择将同享变量用同步代码块包裹或用volatile修饰同享变量。

    为何volatile能保证同享变量的内存可见性?

    volatile修饰了1个成员变量后,这个变量的读写就会比普通变量多1些步骤。

    • volatile变量写
      当被volatile修饰的变量进行写操作时,这个变量将会被直接写入同享内存,而非线程的专属存储空间。

    • volatile变量读
      当读取1个被volatile修饰的变量时,会直接从同享内存中读,而非线程专属的存储空间中读。

    通过对volatile变量读写的限制,就可以保证线程每次读到的都是最新的值,从而确保了该变量的内存可见性。

    volatile变量赠送的附加功能

    进行volatile写操作时,不但会将volatile变量写入同享内存,系统还会将当前线程专属空间中的所有同享变量写入同享内存。
    进行volatile读操作时,系统也会1次性将同享内存中所有同享变量读入线程专属空间。
    这就意味着,如果普通变量在volatile写操作之前被修改,那末在volatile读操作以后就可以正确读到他们。
    但是,在volatile写操作以后被修改的普通变量 和 在volatile读操作之前被访问的普通变量 都不具有内存可见性。

    6.3 原子性

    甚么是原子性?

    原子性指的是1组操作必须1起完成,中途不能被中断。

    volatile能确保long、double读写的原子性

    在Java中的所有类型中,有long、double类型比较特殊,他们占据8字节(64比特),其余类型都小于64比特。在32位操作系统中,CPU1次只能读取/写入32位的数据,因此对64位的long、double变量的读写会进行两步。在多线程中,若1条线程只写入了long型变量的前32位,紧接着另外一条线程读取了这个只有“1半”的变量,从而就读到了1个毛病的数据。
    为了不这类情况,需要在用volatile修饰long、double型变量。

    在内存可见性与原子性上,volatile就相当因而同步的setter和getter函数。但其实不具有volatile的重排序规则,同步块只确保同步块内部的指令不产生重排序,其实不确保同步块之外的指令的重排序。

    PS1:Java中的byte居然是字节,bit才是比特(位)。
    PS2:char和short⑵字节、int和float⑷字节、long和double⑻字节、byte⑴字节

    QA:在同步块中调用wait函数是不是会破坏原子性?

    波比源码 – 精品源码模版分享 | www.bobi11.com
    1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
    2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
    3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
    4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
    5. 如有链接无法下载、失效或广告,请联系管理员处理!
    6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
    7. 如遇到加密压缩包,请使用WINRAR解压,如遇到无法解压的请联系管理员!

    波比源码 » Java并发编程的艺术(三)——volatile

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    波比源码
    一个高级程序员模板开发平台
    升级波友尊享更多特权立即升级