java赋值语句_java并发编程之原子性问题
程序是否線程安全,取決于哪些要素呢,主要是以下三個:
原子性,
可見性,
有序性。
今天先一起來學習原子性。
原子性:
我理解一個操作不可再分,即為原子性。而在并發編程的環境中,原子性的含義就是只要該線程開始執行這一系列操作,要么全部執行,要么全部未執行,不允許存在執行一半的情況。
老生常談的銀行轉賬情況用于理解(僅限于理解,真實的銀行轉賬沒這么簡單):
A賬戶向B賬戶轉錢,A賬戶轉出1萬元,銀行就必須保證B賬戶收到1萬元,即使有問題,也必須保證是A賬戶轉出失敗,錢還在A賬戶。不然A賬戶轉了,B賬戶卻沒收到,銀行的操作就不是原子性的,客戶的利益受到損失。
談及原子性問題,需要先了解Java內存模型的基本情況:
為了執行效率,java的內存被劃分為工作內存與主內存(可類比為計算機的高速緩存與內存),如下圖所示:
線程與工作內存和主內存
工作內存中,放著線程使用的主內存的拷貝。線程對變量的操作必須通過工作內存進行,而不能直接訪問主內存,工作內存直接相互獨立。
內存模型中,還定義了八種原子的操作指令,供程序使用,如下所示:
-----內容參考:《深入理解java虛擬機》----begin
lock(鎖定):作用于主內存,它把一個變量標記為一條線程獨占狀態;
read(讀取):作用于主內存,它把變量值從主內存傳送到線程的工作內存中,以便隨后的load動作使用;
load(載入):作用于工作內存,它把read操作的值放入工作內存中的變量副本中;
use(使用):作用于工作內存,它把工作內存中的值傳遞給執行引擎,每當虛擬機遇到一個需要使用這個變量的指令時候,將會執行這個動作;
assign(賦值):作用于工作內存,它把從執行引擎獲取的值賦值給工作內存中的變量,每當虛擬機遇到一個給變量賦值的指令時候,執行該操作;
store(存儲):作用于工作內存,它把工作內存中的一個變量傳送給主內存中,以備隨后的write操作使用;
write(寫入):作用于主內存,它把store傳送值放到主內存中的變量中。
unlock(解鎖):作用于主內存,它將一個處于鎖定狀態的變量釋放出來,釋放后的變量才能夠被其他線程鎖定;
Java內存模型還規定了執行上述8種基本操作時必須滿足如下規則:
1、不允許read和load、store和write操作之一單獨出現(即不允許一個變量從主存讀取了但是工作內存不接受,或者從工作內存發起會寫了但是主存不接受的情況),以上兩個操作必須按順序執行,但沒有保證必須連續執行,也就是說,read與load之間、store與write之間是可插入其他指令的。
2、不允許一個線程丟棄它的最近的assign操作,即變量在工作內存中改變了之后必須把該變化同步回主內存。
3、不允許一個線程無原因地(沒有發生過任何assign操作)把數據從線程的工作內存同步回主內存中。
4、一個新的變量只能從主內存中“誕生”,不允許在工作內存中直接使用一個未被初始化(load或assign)的變量,換句話說就是對一個變量實施use和store操作之前,必須先執行過了assign和load操作。
5、一個變量在同一個時刻只允許一條線程對其執行lock操作,但lock操作可以被同一個條線程重復執行多次,多次執行lock后,只有執行相同次數的unlock操作,變量才會被解鎖。
6、如果對一個變量執行lock操作,將會清空工作內存中此變量的值,在執行引擎使用這個變量前,需要重新執行load或assign操作初始化變量的值。
7、如果一個變量實現沒有被lock操作鎖定,則不允許對它執行unlock操作,也不允許去unlock一個被其他線程鎖定的變量。
8、對一個變量執行unlock操作之前,必須先把此變量同步回主內存(執行store和write操作)。
-----內容參考:《深入理解java虛擬機》----end
因此我們寫了一個程序,就很容易判斷是否是具備原子性的,如下所示:
int x = 10; //語句1
long y=100;//語句2
int z = x; //語句3
x++; //語句4
z = z + 1; //語句5
volatile int a=0;
a=x;//語句6
語句1:只執行了assign語句,將10賦給工作內存中的x,原子的。
語句2:由于long類型為64位的,java可能會出現寫兩次32位數據到工作內存的情況,導致操作是非原子的(幾乎所有虛擬機都對這種操作進行了封裝,使其變為和原子操作)
語句3:use獲取x的值,再assign賦值給z,非原子的。
語句4:user獲取x的值,加1,在assign賦值給x,非原子的。
語句5:user獲取z的值,加1,在assign賦值給z,非原子的。
語句6:use獲取x的值,assign賦值給a,并且馬上store將a的新值存儲到主內存中,并將其他工作線程中的a值失效,非原子的。 如果其他線程要獲取a的值,需要對應的工作內存重新從主內存中獲取(volatile的可見性原理)。
感興趣的小伙伴歡迎關注我的公眾號:暖爸的java家園
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的java赋值语句_java并发编程之原子性问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: uboot移植9个步骤_不知道具体的新房
- 下一篇: javadoc文档的生成方法_[spri