天天看点

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);
	}

}