Java原子类Atomic原理和应用

jdk所提供的原子类可以大致分为四种类型:

  1. 原子更新基本数据类型
  2. 原子更新数组类型
  3. 原子更新抽象数据类型
  4. 原子更新字段
     

先来看看jdk提供的原子类(rt.jar包下java.util.concurrent.atomic):

Java原子类Atomic原理和应用_第1张图片

 

首先我们来写一个数字自增生成器

package cn.itcats.thread.safe.Test1;

public class Sequence {
	private int a = 0;

	public  int add() {
		return a++;
	}

	public static void main(String[] args) {
		Sequence sequence = new Sequence();
		new Thread(new Runnable() {
			public void run() {
				while (true) {
					try {
						Thread.sleep(200);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName() + "   " + sequence.add());
				}
			}
		}).start();

		new Thread() {
			public void run() {
				while (true) {
					try {
						Thread.sleep(200);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName() + "   " + sequence.add());
				}
			};
		}.start();

	}
}

 

列出部分的运行结果:

Thread-0   0
Thread-1   0
Thread-1   1
Thread-0   1
Thread-1   2
Thread-0   3
Thread-1   4
Thread-0   5

明显可见存在线程安全问题,这也就是我们正需要解决的问题

add()方法中   a++;    并不是一个原子性操作,我们使用原子类把int a变成一个原子类

package cn.itcats.thread.safe.Test1;

import java.util.concurrent.atomic.AtomicInteger;

public class Sequence {
	//使用原子类AtomicInteger
	private AtomicInteger a = new AtomicInteger(0);

	public  int add() {
		return a.getAndIncrement();   //先获取再自增,对应a++   
		//若使用++a 则对应方法是a.incrementAndGet(); 先自增再获取 , 
		//多说一句  a-- 就是  a.getAndDecrement();   
		//若a = a + 10;————对应API  a.getAndAdd(10);
	}

	public static void main(String[] args) {
		Sequence sequence = new Sequence();
		new Thread(new Runnable() {
			public void run() {
				while (true) {
					try {
						Thread.sleep(200);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName() + "   " + sequence.add());
				}
			}
		}).start();

		new Thread() {
			public void run() {
				while (true) {
					try {
						Thread.sleep(200);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName() + "   " + sequence.add());
				}
			};
		}.start();

	}
}

再看运行结果发现,并没有出现重复的数字。因此我们对数值的一些非原子性操作,都可以使用原子类转化为原子性操作。

除了对int等基本数据类型的操作,还可以对数组使用原子类进行原子性操作。

private int[] s = {1,2,3};
AtomicIntegerArray array = new AtomicIntegerArray(s);
public int arrayAdd() {
		return array.getAndAdd(0, 10);
	}

对原子更新抽象数据类型进行设置和获取    AtomicReference at = new AtomicReference();

原子更新字段 如更新User字段属性  

AtomicIntegerFieldUpdater userAto = AtomicIntegerFieldUpdater.newUpdater(User.class,"name");

相关API不一一说明了,因为用的不算太多。

 

 

你可能感兴趣的:(Java多线程)