亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定

第三章 Java內存模型之volatile⑥

標簽:
Java

理解volatile特性,一个好方法就是把volatile变量的单个读、写 ,可以看成是使用同一个锁对这些单个读/写进行了同步。

class demo{volatile long v1 = 0L;public void set(long l){
v1 = l;
}public long get(){return v1;
}

}
class demo{ long v1 = 0L;public synchronized void set(long l){
v1 = l;
}public synchronized long get(){return v1;
}

}

上面的两段代码效果是一样的。

我们都知道锁的 happens-before 规则来保证释放锁和获取锁的两个线程之间的内存可见性。所以意味着一个 volatile 变量的读,总是能看到(任意线程)对这个 volatile 变量的最后写入。

锁的语义决定了临近区代码的执行具有原子性,即使64位的 long 或者 double 变量,只要是 volatile 变量,那么该变量的读/写就具有原子性。但是多个  volatile  操作或者  volatile++ 是不具有原子性的。

volatile 具有以下特性:

1)可见性。 对一个 volatile 变量的读,总是能看到(任意线程)对这个 volatile 变量的最后写入。
2)原子性。对任意的那个 volatile 变量的读/写都具有原子性。但是类似于 volatile++ 不具备。

对于程序员来说,volatile 对线程的内存可见性影响比 volatile 自身的特性更重要。volatile 的读/写可以实现线程之间的通信。

对比锁的释放-获得对内存的影响,volatile 也具有相同的内存语义。volatile 读==锁的获取。volitle 写 == 锁的释放。

当写一个 volatile  变量时,JMM 会把该线程对应的本地内存中的共享变量值刷新到主内存中。
当读取一个 volatile 时,JMM 会把该线程对应的本地内存置为无效,然后从主内存中读取共享变量。

总结一下 volatile 的读/写:

1)线程 A 写一个 volatile 变量,实际上是线程 A 向接下来将要读这个 volatile 变量的某个线程发出来(其对共享变量所做的修改的)消息。
2)线程 B 读一个 volatile 变量,实际上是线程 B  接收了之前某个线程发出的(在写这个 volatile 变量之前对这个共享变量修改的)消息。
3)程序 A 写一个 volatile 变量,随后程序 B 读这个 volatile 变量,这个过程实质上就是线程 A 通过主内存向线程 B 发送消息。

其实也印证了我们之前所说的共享内存的通信是隐性的。

为了实现 volatile ,JMM限制了编译器和处理器的重排序。


webp

重排序规则

总结一下这个规则:

1、当第二个操作是 volatile 写的时候,不管第一个操作是啥,都不允许重排序。确保 volatile 写之前的操作不会被编译器重排序到 volatile 写之后。

2、当第一个操作是 volatile 读的时候,不管第二个操作是啥,都不允许重排序。确保 volatile 读之后的操作不会被编译器重排序到 volatile 读之前。



作者:猪_队友
链接:https://www.jianshu.com/p/4377a099c15e


點擊查看更多內容
TA 點贊

若覺得本文不錯,就分享一下吧!

評論

作者其他優質文章

正在加載中
  • 推薦
  • 評論
  • 收藏
  • 共同學習,寫下你的評論
感謝您的支持,我會繼續努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦
今天注冊有機會得

100積分直接送

付費專欄免費學

大額優惠券免費領

立即參與 放棄機會
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號

舉報

0/150
提交
取消