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