setnx是原子操作吗_谈谈Volatile关键字?为什么不能保证原子性?用什么可以替代?为什么?...
大家好,歡迎關注我的公眾號碼猿bug,需要資料的話可以加我微信好友。
再談volatile關鍵字之前,首先必須聊聊JMM內存模型!
JMM主要的特性:可見性、原子性,順序性
Java 虛擬機規范試圖定義一種 Java 內存模型(JMM),來屏蔽掉各種硬件和操作系統的內存訪問差異,讓 Java 程序在各種平臺上都能達到一致的內存訪問效果。簡單來說,由于 CPU 執行指令的速度是很快的,但是內存訪問的速度就慢了很多,相差的不是一個數量級,所以搞處理器的那群大佬們又在 CPU 里加了好幾層高速緩存。在 Java 內存模型里,對上述的優化又進行了一波抽象。JMM 規定所有變量都是存在主存中的,類似于上面提到的普通內存,每個線程又包含自己的工作內存,方便理解就可以看成 CPU 上的寄存器或者高速緩存。所以線程的操作都是以工作內存為主,它們只能訪問自己的工作內存,且工作前后都要把值在同步回主內存。
網上找的一些定義:
簡單描述如下:
- 主存存放線程需要操作的變量,但線程并不直接操作主存。
- 每個線程讀取主存變量都是先拷貝一份到工作內存中,不同線程工作內存互不干擾。
- 線程修改了工作內存后,再寫回主存中。
- 每次從主存讀寫的過程都需要經過原子性操作。
簡單知道了java的內存模型,那開始聊聊volatile關鍵字。volatile關鍵字有三大特性:
①可見性
②不保證原子性
③禁止指令重排
首先要知道volatile是java虛擬機提供的輕量級的同步機制,volatile的可見性是由jvm發送一條lock前綴的匯編指令實現的。volatile關鍵字是修飾成員變量的,也就是說,如果一個成員變量加了volatile關鍵字,就會告訴編譯器和jvm的內存模型,這個變量是對所有線程共享的,可見性每次JVM都會讀取最新寫入的值并使其最新值在所有的cpu可見。volatile可以保證線程的可見性并且提供了一定的順序性,但是無法保證原子性。在JVM底層volatile是采用內存屏障來實現的。使用了volatile關鍵字就好像是線程直接操作了主內存。
為什么不能保證原子性呢?
在我們的程序中,即使加了volatile也不能保證原子性,有一種粗暴的解決辦法,就是加我們的synchronized同步鎖,但是這種鎖太重了。簡單畫個圖演示為什么不能保證原子性。
在程序中的i++操作,是不能保證原子性的.
那原子性和可見性不是就沖突了嗎?不沖突
因為volatile 的可見性只能對應l原子性, a=1是原子性,而a++實際上是a=a+1 是非原子性的,所以會導致你說的情況,這時候就要引入同步,強制將a++轉化為原子性。
那除了synchronized還有其他解決辦法嗎?
那就是大名鼎鼎的JUC包下的AtomicInteger,寫一小段程序說明:
AtomicInteger那為什么用AtomicInteger就能保證原子性呢?因為他的底層是CAS,接下來就要說說什么是cas了。
cas是compare and set的縮寫,比較并交換,unsafe是cas的核心類,cas的底層是靠的unsafe類來保證原子性的,unsafe是jvm下的rt.jar的運行jar包里面。
跟進源代碼可以看見這段代碼:
public final int getAndIncrement(){return unsafe.getAndAddInt(this,1);//這個1是值的valueoffset:內存地址偏移量 }還靠的是一段do while循環,顧名思義,又叫自旋鎖
這時候就應該思考,為什么在沒有加鎖的情況下,還能保證線程安全呢?
①因為atomicInteger借助了UnSafe提供的CAS操作能夠保證數據更新的時候是線程安全的,那么為什么借助了unsafe就能保證線程安全呢?以下總結出自我的筆記
②
因為cas并發原語體現在JAVA語言中就是sun.misc.Unsafe類中的各個方法。調用Unsafe類中的CAS方法,JVM會幫我們實現匯編指令,這是一種完全依賴的硬件功能。通過他實現了原子操作。并且原語的執行必須是連續的,在執行過程中不允許被中斷,也就是說CAS是一條CPU的原子指令,不會造成所謂的數據不一致問題,保證了線程安全。
下一篇文章中會繼續討論CAS的缺點以及volatile的應用場景。技術小白一枚,希望各位大佬指出錯誤,互相討論。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的setnx是原子操作吗_谈谈Volatile关键字?为什么不能保证原子性?用什么可以替代?为什么?...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: service层中有某个事物要立马提交_
- 下一篇: 草鱼鳔的功效与作用、禁忌和食用方法