voliatle關鍵字

1.volatile關鍵字使用:

  多線程中存在私有堆棧中的值和公共堆棧中的值不一樣步的問題。什麼意思呢?可能線程在一個地方修改了內存中變量的值,而其它地方線程卻從私有堆棧中去讀取不一致的變量值。關鍵字volatile 的主要做用是使在多個線程上可見。也就是,強制從公共堆棧中取得變量的值,而不是從線程私有數據棧中取得變量的值。java

  • 線程的私有堆棧:

  • 讀取公共內存:

強制從私有堆棧中取值的方法爲JVM被設置爲-server(不設置-server也是從私有堆棧中獲取值)。安全

package chapter2;

public class VolatileTest {
	
	
	static class RunThread extends Thread{
	        private boolean isRunning = true;

		public boolean isRunning() {
			return isRunning;
		}

		public void setRunning(boolean isRunning) {
			this.isRunning = isRunning;
		}
		
		@Override
		public void run() {
			super.run();
			System.out.println("進入run 了");
			while (isRunning) {
				
			}
			System.out.println("線程被中止了!");
		}
	}
	
	public static void main(String[] args) {
		try {
			RunThread runThread = new RunThread();
			runThread.start();
			Thread.sleep(1000);
			runThread.setRunning(false);
			System.out.println("已經賦值爲false");
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}

運行結果:多線程

進入run 了
已經賦值爲false
永遠不會打印線程被中止了!ide

volatile private boolean isRunning = true;//強制從公共堆棧中取得變量的值this

運行結果:atom

進入run 了
已經賦值爲false
線程被中止了!線程

非原子性驗證:

package chapter2;

public class VolatileThread extends Thread{
	volatile public static int count;
	private static void addCount() {
		for(int i=0;i<100;i++) {
			count++;
		}
		System.out.println("Thread:"+currentThread().getName()+"--count:"+count);
	}
	
	@Override
	public void run() {
		super.run();
		addCount();
	}

}

 

package chapter2;

public class VolatileTest {
	
	public static void main(String[] args) {
		VolatileThread[] volatileThreads = new VolatileThread[100];
		for (int i = 0; i < 100; i++) {
			volatileThreads[i] = new VolatileThread();
		}
		
		for(int i=0;i<100;i++) {
			volatileThreads[i].start();
		}
	}

}

 運行結果:3d

Thread:Thread-84--count:8683
Thread:Thread-88--count:8863
Thread:Thread-89--count:8863
Thread:Thread-87--count:8963
Thread:Thread-90--count:9063
Thread:Thread-92--count:9163
Thread:Thread-97--count:9663
Thread:Thread-96--count:9563
Thread:Thread-98--count:9763
Thread:Thread-95--count:9863
Thread:Thread-93--count:9463
Thread:Thread-94--count:9363
Thread:Thread-91--count:9263
Thread:Thread-99--count:9963

server

非原子性的緣由:

  • read 和 load 階段:從主存複製變量到當前線程工做內存。
  • use 和 assign 階段:執行代碼,改變共享變量值。
  • store 和 write 階段:用工做內存數據刷新主存對應變量的值。

   在多線程環境中,use和assign 是屢次出現的,但這一操做並非原子性,也就是說在read和load以後,若是主內存count變量發生修改以後,線程工做內存中的值因爲已經加載,不會產生對應的變化,也就是私有內存和公有內存的變量不一樣步,因此計算出來的結果和預期不同,也就出現了非線程安全的問題。blog

2.使用原子類進行i++操做

package chapter2;

import java.util.concurrent.atomic.AtomicInteger;

public class VolatileThread extends Thread{
	private AtomicInteger count = new AtomicInteger(0);
	private void addCount() {
		for(int i=0;i<10000;i++) {
			System.out.println(count.incrementAndGet());
		}
	}
	
	@Override
	public void run() {
		super.run();
		addCount();
	}

}

 

package chapter2;

public class VolatileTest {
	
	public static void main(String[] args) {
		try {
			VolatileThread volatileThread = new VolatileThread();
			Thread t1 = new Thread(volatileThread);
			t1.start();
			Thread t2 = new Thread(volatileThread);
			t2.start();
			Thread t3 = new Thread(volatileThread);
			t3.start();
			Thread t4 = new Thread(volatileThread);
			t4.start();
			Thread t5 = new Thread(volatileThread);
			t5.start();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}

運行結果:

49990
49991
49992
49993
49994
49995
49996
49997
49998
49999
50000

成功累加到50000!

相關文章
相關標籤/搜索