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