1. 程式人生 > >java原子變數

java原子變數

變數的賦值程式碼體現為一條語句,但是對應的虛擬機器編譯後的位元組碼就可能是多條語句。因此,在多執行緒環境下,單個變數的賦值可能會出現意想不到的問題。

java5後增加了“原子變數”的概念,目前支援的“原子變數”有AtomicInteger、AtomicLong、Integer和Long的“原子陣列”變數AtomicIntegerArray和AtomicLongArray。

這些原子變數實現的原理是被稱為“CAS”操作的方法實現的。根據統計使用原子變數解決執行緒安全問題的效能優於使用“鎖”。

我分別寫了兩套程式去驗證,雖然使用Integer沒有驗證出問題,但是並不排除。

定義Company類,Company中有AtomicInteger型別的account變數,一個執行緒預設將account遞增1000.

定義User類,User中也有AtomicInteger型別的accout變數,對應於Company,一個執行緒預設將account遞減1000。

測試方法分別起動1000個執行緒,account的初始值為1000,看最終的結果來判斷。

package com.z;

import java.util.concurrent.atomic.AtomicInteger;

public class Company implements Runnable{

	private AtomicInteger count;
	
	public Company(AtomicInteger count){
		this.count = count;
	}
	
	@Override
	public void run(){
		for(int i = 0; i < 1000; i ++){
			count.getAndIncrement();
		}
	}
	
}

package com.z;

import java.util.concurrent.atomic.AtomicInteger;

public class User implements Runnable {
	
	private AtomicInteger count;
	
	public User(AtomicInteger count){
		this.count = count;
	}

	@Override
	public void run() {
		for(int i = 0; i < 1000; i ++)
			count.getAndDecrement();
	}

}

package com.z;

import java.util.concurrent.atomic.AtomicInteger;

public class Test {
	
	public static void main(String[] args){
		
		for(int i = 1; i <= 100; i ++){
			System.out.println("                 第"+i+"次執行");
			count();
		}
		
	}
	
	public static void count(){
		AtomicInteger oriCount = new AtomicInteger(1000);
		int COMPANY_NUM = 1000;
		int USER_NUM = 1000;
		Thread[] company = new Thread[COMPANY_NUM];
		Thread[] user = new Thread[USER_NUM];
		
		for(int i = 0; i < COMPANY_NUM; i ++){
			company[i] = new Thread(new Company(oriCount));
			company[i].start();
		}
		
		for(int i = 0; i < USER_NUM; i ++){
			user[i] = new Thread(new User(oriCount));
			user[i].start();
		}
		
		try {
			for(int i = 0; i < COMPANY_NUM; i ++)
				company[i].join();
			for(int i = 0; i < USER_NUM; i ++)
				user[i].join();
		} catch (InterruptedException e) {
			System.out.println("company or user join() is fail");
		}
		
		System.out.println("最終計算結果是:" + oriCount.get());
	}

}

Integer測試,對照以上程式碼:
package com.z;

public class LowCompany implements Runnable{

	private Integer count;
	
	public LowCompany(Integer count){
		this.count = count;
	}
	
	@Override
	public void run(){
		for(int i = 0; i < 1000; i ++){
			count++;
		}
	}
	
}
package com.z;

public class LowUser implements Runnable {
	
	private Integer count;
	
	public LowUser(Integer count){
		this.count = count;
	}

	@Override
	public void run() {
		for(int i = 0; i < 1000; i ++)
			count--;
	}

}


package com.z;


public class LowTest {
	
	public static void main(String[] args){
		
		for(int i = 1; i <= 1000; i ++){
			System.out.println("                 第"+i+"次執行");
			count();
		}
		
	}
	
	public static void count(){
		Integer oriCount = new Integer(1000);
		int COMPANY_NUM = 1000;
		int USER_NUM = 1000;
		Thread[] company = new Thread[COMPANY_NUM];
		Thread[] user = new Thread[USER_NUM];
		
		for(int i = 0; i < COMPANY_NUM; i ++){
			company[i] = new Thread(new LowCompany(oriCount));
			company[i].start();
		}
		
		for(int i = 0; i < USER_NUM; i ++){
			user[i] = new Thread(new LowUser(oriCount));
			user[i].start();
		}
		
		try {
			for(int i = 0; i < COMPANY_NUM; i ++)
				company[i].join();
			for(int i = 0; i < USER_NUM; i ++)
				user[i].join();
		} catch (InterruptedException e) {
			System.out.println("company or user join() is fail");
		}
		
		System.out.println("最終計算結果是:" + oriCount);
	}

}