java Atomic原子性

package com.huateng.atomic;

import java.util.concurrent.atomic.AtomicInteger;
/**
 * 普通的不加鎖情況,increment方法內分兩個步驟,get value和value+1
 * 期望的流程是:線程1走完value+1後線程2開始get value
 * 當發生線程1已經get value且沒有value+1時線程2開始get value,這個值就比期望值少1
 * synchronize意思是強制線程1走完value+1才允許線程2開始
 * 
 * Atomic的區別在:普通的int類型爲每個線程分配工作區間,線程1的set value+1必定是操作線程1的get value
 * 		而AtomicInteger當線程1在get value和set value之間別的線程也做了set value
 * 		則compareAndSet會發現本線程1的value值已被其他線程改變
 * 		從而重新get value,這時get的值是線程2改變過的新值了
 * 意思是get和set之間不會被其他線程干擾,所以被稱作原子性
 * 		
 * @author huateng
 *
 */
public class Increment4 extends Thread{
	private Counter2 counter;
	public Increment4(Counter2 counter){
		this.counter = counter;
	}
	public void run(){
		try {
			Thread.sleep(10);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		counter.increment();
	}
	public static void main(String[] args) throws Exception{
		int size = 10000;
		long start = System.currentTimeMillis();
		Counter2 counter = new Counter2();
//		for(int i=0;i<10000;i++){
//			new Increment4(counter).start();
//		}
//		Thread.sleep(5888);
		Thread[] threads1 = new Thread[size];
		/**
		 * 這裏用for(Thread t:threads1)不能向數組裏面賦值,調用時空指針
		 */
//		for(Thread t:threads1){
//			t = new Increment4(counter);
////			t.start();
//			System.out.println("t: "+t);
//		}
		for(int i=0;i<size;i++){
			threads1[i] = new Increment4(counter);
		}
		for(Thread t:threads1){
			t.start();
		}
		for(Thread t:threads1){
			t.join();
		}
		System.out.println("counter: "+counter.getValue());
		long end = System.currentTimeMillis();
		System.out.println("Atomic cost time: "+(end-start));
		
		Counter3 counter3 = new Counter3();
//		for(int i=0;i<10000;i++){
//			new Increment5(counter3).start();
//		}
//		Thread.sleep(5888);
		Thread[] threads2 = new Thread[size];
//		for(Thread t:threads2){
//			t = new Increment5(counter3);
////			t.start();
//		}
		for(int i=0;i<size;i++){
			threads2[i] = new Increment5(counter3);
		}
		for(Thread t:threads2){
			t.start();
		}
		for(Thread t:threads2){
			t.join();
		}
		System.out.println("counter3: "+counter3.getValue());
		long end2 = System.currentTimeMillis();
		System.out.println("synchronized cost time: "+(end2-end));
	}
}
class Increment5 extends Thread{
	private Counter3 counter3;
	public Increment5(Counter3 counter3) {
		this.counter3 = counter3;
	}
	public void run(){
		try {
			Thread.sleep(10);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		counter3.increment();
	}
}
class Counter2{
	private AtomicInteger value = new AtomicInteger(0);
	public AtomicInteger getValue() {
		return value;
	}
	public void setValue(AtomicInteger value) {
		this.value = value;
	}
	public void increment(){
		value.incrementAndGet();//跟下面for循環寫法一樣
//		for(;;){
//			int current = value.get();
//			int next = current + 1;
//			if(value.compareAndSet(current, next)){
//				return ;
//			}
//		}
	}
}
class Counter3{
	private int value = 0;
	public int getValue() {
		return value;
	}
	public void setValue(int value) {
		this.value = value;
	}
	public synchronized void increment(){
		++value;
	}
}
//counter: 10000
//Atomic cost time: 2448
//counter3: 10000
//synchronized cost time: 2377


join方法意思是等待線程完成,如果改成Thread.sleep(5555)也會得到正確值。不然,main線程走到print語句時,10000個線程的加法會有一些還沒有完成,得到的值將<10000

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章