1. 程式人生 > >併發程式設計——為什麼volatile變數++操作執行緒不安全

併發程式設計——為什麼volatile變數++操作執行緒不安全

學習volatile的時候也許我們會看到下面這句話:

對於volatile變數來說,自增操作執行緒不安全。

 

那為什麼不安全呢?本帥博主看的是《併發程式設計的藝術》這本書,這本書對這一事件也沒有做出很讓人易懂的解釋。那麼我們自己用例子來測試一下咯~

測試程式碼如下: 

package xiancheng;

public class volatileTest {

	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		VolatileExample example=new VolatileExample();
		Thread thread1=new Thread() {
			public void run(){
				for(int i=0;i<100000;i++) {
					example.getAndIncrement();
				}
			}
		};
		Thread thread2=new Thread() {
			public void run(){
				for(int i=0;i<100000;i++) {
					example.getAndIncrement();
				}
			}
		};
		thread1.start();
		thread2.start();
		Thread.sleep(6000);//等一會,讓執行緒都執行完。
		System.out.println(example.get());
	}

}

class VolatileExample{
	volatile int v=0;
	public  void set(int  l) {
		v=l;
	}
	public void getAndIncrement() {
        v++;
	}
	public  int get() {
		return v;
	}
}

在上面這個程式碼中,VolatileExample類彙總聲明瞭一個volatile變數v,以及三個方法,set()、get()和用來進行自增操作的getAndIncrement()方法。

在主函式中,我建立了兩個執行緒,各自迴圈呼叫VolatileExample類的例項volatileExample中的getAndIncrement()方法100000次。

如果volatile保證++安全,那麼執行結果將是200000.

那麼真實結果是多少呢?

多執行幾次:

    

從上面幾次的執行結果我們可以看到,始終都不到200000萬。這樣的結果表明volatile不保證volatile++這樣的操作具有原子性。

為什麼呢?

其實很簡單,因為“++”屬於複合操作。

上面的VolatileExample其實等價於一下的程式碼:

class VolatileExample{
	int v=0;
	public synchronized void set(int  l) {
		v=l;
	}
	public void getAndIncrement() {
		int temp=get();
		temp+=1;
		set(temp);
	}
	public synchronized int get() {
		return v;
	}
	
	
}

如果不清晰的話,我們可以通過javap反編譯一下。 

使用javap對VolatileExample類進行反編譯,出來的結果如下: 

我們可以看到,getAndIncrement()方法中的v++語句被編譯成了 七條語句,這屬於複合操作。

v++其實相當於:

  1. 讀v
  2. 對v+1;
  3. 將原來的v值置為v+1。

 volatile保證可見性,當進行++操作的時候,volatile保證第一條指令正確,即讀正確。當執行接下來的指令的時候,其他執行緒可能對v加大了,當將v存回去的時候(即執行putfield指令的時候),可能將一個更小的v同步回主記憶體去了。所以最終得到的數字就會小於200000.

總結:volatile的讀寫具有原子性,但是自增操作屬於複合操作,因此不具有原子性,所以執行緒也不安全。

 

好啦,以上就是關於volatile變數自增是否執行緒安全的相關知識總結,如果大家有什麼不明白的地方或者發現文中有描述不好的地方,歡迎大家留言評論,我們一起學習呀。

 

Biu~~~~~~~~~~~~~~~~~~~~宫å´éªé¾ç«è¡¨æå|é¾ç«gifå¾è¡¨æåä¸è½½å¾ç~~~~~~~~~~~~~~~~~~~~~~pia!