1. 程式人生 > >java 並發原子性與易變性 來自thinking in java4 21.3.3

java 並發原子性與易變性 來自thinking in java4 21.3.3

tom element mat check vol 競爭 -s argument track

java 並發原子性與易變性 具體介紹請參閱thinking in java4 21.3.3

thinking in java 4免費下載:http://download.csdn.net/detail/liangrui1988/7580155

package org.rui.thread.volatiles;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
 * 假設你盲目地應用原子性慨念。那麽就會看到在以下程序中的getValue符合上面的描寫敘述
 * 
 * 可是,該程序將找到奇數值並終止。雖然return i確實是原子性操作。可是缺少同步使得其數值能夠在處於不穩定的中間狀態時被讀取。
 * 除此之外,因為i也不是volatile的,因此還存在可視性問題
 * @author lenovo
 *
 */
public class AtomicityTest implements Runnable {

	private int i=0;
	public int getValue(){return i;}
	private synchronized void evenIncrement(){i++;i++;}
	@Override
	public void run() {
		while(true)
			evenIncrement();
		
	}
	
	public static void main(String[] args) {
		ExecutorService exec=Executors.newCachedThreadPool();
		AtomicityTest at=new AtomicityTest();
		exec.execute(at);
		while(true)
		{
			int val=at.getValue();
			if(val%2!=0)
			{
				System.out.println(val);
				System.exit(0);
			}
		}
	}

}

package org.rui.thread.volatiles;
/**
 * 考慮一些更簡單的事情。一個產生序列數字的類,
 * 每當nextSerial-Number被調用時,它必須向調用者返回唯一的值
 * @author lenovo
 *
 */
public class SerialNumberGenerator {

	private static volatile int serialNumber=0;
	public static int nextSerialNumber()
	{
		return serialNumber++;//非線程安全
	}
}

package org.rui.thread.volatiles;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
 * 為了測試SerialNumberGenerator 我們須要不會耗盡內存的集(SET) 。
 * 以防須要花費非常長的時間來探測問題。

這裏所看到的的circularSet重用了存儲int數值的內存, * 並假設在你生成序列數時,產生數值覆蓋沖突的可能性極小。add 和contains 方法都 是synchronized,以防示線程沖突 * @author lenovo * */ //重用存儲所以我們不耗盡內存 //reuses storage so we don't run out of memory class CircularSet { private int[] array; private int len; private int index=0; public CircularSet(int size){ array=new int[size]; len=size; //初始化一個值而不是生產 //這個初始全是-1和serialNumberGenerator 不同樣。其後取serialNumberGenerator.next...存入 //by the serialNumberGenerator; for(int i=0;i<size;i++) array[i]=-1; } //add public synchronized void add(int i) { array[index]=i; //wrap index and write over old elements; 將指數和寫在舊元素; index=++index % len; //System.out.println(index+" : len :"+len); } //contains public synchronized boolean contains(int val) { for(int i=0;i<len;i++) { System.out.println(array[i]+" == "+val); if(array[i]==val) return true; } return false; } } /////////////////////////////////////////////// public class SerialNumberChecker { private static final int SIZE=10; private static CircularSet serials=new CircularSet(1000); private static ExecutorService exec=Executors.newCachedThreadPool(); static class SerialChecker implements Runnable { @Override public void run() { while(true) { //自增長 int serial=SerialNumberGenerator.nextSerialNumber(); if(serials.contains(serial)) { //反復 System.out.println("Duplicate: "+serial); System.exit(0); } serials.add(serial); } } } //// public static void main(String[] args) throws NumberFormatException, InterruptedException { String[] arg=new String[]{"10000"}; for(int i=0;i<SIZE;i++) { exec.execute(new SerialChecker()); //stop after n seconds if there 's an argument 停止在n秒後假設有一個論點 if(arg.length>0) { TimeUnit.SECONDS.sleep(new Integer(arg[0])); System.out.println("沒有反復檢測"); System.exit(0); } } } } /** * 通過創建多個任務來競爭序列數,你將發現這些任務終於會得到反復的序列數,假設你執行的時間足夠長的話 * 為了解決問題,nextSerialNumber 前面加入 了synchronized關健字 */



java 並發原子性與易變性 來自thinking in java4 21.3.3