1. 程式人生 > >Java同步—並發三大性質

Java同步—並發三大性質

vol 寫在前面 導致 () www. hid 中斷 多個 規則

Java並發三大性質

在Java內存模型中,有三大性質:原子性有序性可見性.

原子性:即一個操作或者多個操作,要麽全部執行並且執行的過程不會被任何因素打斷,要麽就都不執行。即使是在多個線程一起執行的時候,一個操作一旦開始,就不會被其它線程幹擾.

有序性:即程序執行的順序按照代碼的先後順序執行.

可見性:當多個線程訪問同一個變量的時候,一旦線程修改了這個變量的值,其他線程能夠李可看到修改的值。

原子性

舉個例子:A想要從自己的帳戶中轉1000塊錢到B的帳戶裏。那個從A開始轉帳,到轉帳結束的這一個過程,稱之為一個事務.在這個事務裏,要做如下操作:

  1. 從A的帳戶中減去1000塊錢。如果A的帳戶原來有3000塊錢,現在就變成2000塊錢了。
  2. 在B的帳戶裏加1000塊錢。如果B的帳戶如果原來有2000塊錢,現在則變成3000塊錢了。

如果在A的帳戶已經減去了1000塊錢的時候,忽然發生了意外,比如停電什麽的,導致轉帳事務意外終止了,而此時B的帳戶裏還沒有增加1000塊錢。那麽,我們稱這個操作失敗了,要進行回滾。

我們把這種要麽一起成功,要麽一起失敗的操作叫原子性操作。

如果把一個事務可看作是一個程序,它要麽完整的被執行,要麽完全不執行.這種特性就叫原子性

舉一個精確的例子:

int x = 1; 
int y = x;  
x++;
x += 1; 

以上四句代碼,一眼看去都是原子性操作,其實裏面只有第1句是原子性操作.

首先我們來了解下計算機的工作方式:

在我們運行程序的時候,CPU會執行程序的每條指令,在執行程序的過程中,肯定會涉及到一些臨時數據,這些數據是存放在內存中的。這就存在一個問題,CPU執行指令的速度比從內存中讀取數據和向內存中寫入數據快很多.如果任何時候操作數據都要從內存中讀寫的話,會大大降低程序的運行速度,因此就有了高速緩存:

在程序運行過程中,會將運算需要的數據從內存復制一份到CPU的高速緩存中,當CPU計算的時候,就可以直接從它的高速緩存中讀寫數據。結束運算後,再將高速緩存中的數據寫入內存中。

我們再回來看一下剛才的四句代碼:

int x=1;//給x賦值為1,這個操作會直接將10寫入內存中
int y=x;//這其實是兩個操作,先讀取x的值,然後將x的值賦值給y再寫入內存中,這兩個操作雖然都是原子性操作,但是合起來就不是原子性操作了
x++;
x+=1;//這兩句代碼包含3個操作,先去讀取x的值,然後進行加1,在把新值寫入到內存中

但是註意一個問題,第一句代碼:

int x=1;//假設x是一個32位的變量,那為它賦值包含兩個過程,給低16位賦值,給高16位賦值,所以也不是原子性操作

可見性

對於可見性,Java提供了volatile關鍵字來保證可見性。

當一個共享變量被volatile修飾的時候,他會保證對值的修改,會立刻被其他共享的線程看見,從而下次加載的時候會從內存中重新取值,而不是從高速緩存中取值,但是volatile變量不能保證原子性。

如果想保證原子性,可以使用synchronizedReentrantLock,他們既可以保證可見性,也可以保證原子性,但是開銷會大很多。

有序性

在Java中,允許編譯器和處理器對指令進行重排序,什麽叫重排序,說簡單點就是改變指令的執行順序。重新排序不會影響單線程執行,卻會影響到多線程並發執行。

同樣,可以使用synchronizedReentrantLock,他們也會保證有序性

但是,我們今天講點額外的東西,Java內存模型中具有一些先天的有序性。也稱為happens-before原則。

happens-before原則:

  • 程序次序規則:一個線程內,按照代碼順序,書寫在前面的操作先行發生於書寫在後面的操作
  • 鎖定規則:一個unLock操作先行發生於後面對同一個鎖的lock操作
  • volatile變量規則:對一個變量的寫操作先行發生於後面對這個變量的讀操作
  • 傳遞規則:如果操作A先行發生於操作B,而操作B又先行發生於操作C,則可以得出操作A先行發生於操作C
  • 線程啟動規則:Thread對象的start()方法先行發生於此線程的每個一個動作
  • 線程中斷規則:對線程interrupt()方法的調用先行發生於被中斷線程的代碼檢測到中斷事件的發生
  • 線程終結規則:線程中所有的操作都先行發生於線程的終止檢測,我們可以通過Thread.join()方法結束、Thread.isAlive()的返回值手段檢測到線程已經終止執行
  • 對象終結規則:一個對象的初始化完成先行發生於他的finalize()方法的開始

轉自:https://www.cnblogs.com/dolphin0520/p/3920373.html

Java同步—並發三大性質