高级并发编程学习-atomic包学习(重点介绍AtomicInteger、AtomicIntegerFieldUpdater)

Java.util.concurrent两个子包locks&atomic,官网文档介绍为可以对基本数据、数组中的基本数据、对类中的基本数据进行操作

一 atomic包

1.      原子性定义:原子性意味着个时刻,只有一个线程能够执行一段代码,这段代码通过一个monitor object保护,从而防止多个线程在更新共享状态时相互冲突。经过atomic类修饰的变量具备原子性,不必考虑在多线程并发条件下的线程安全问题。

(2)对类中的某个成员变量进行修改

使用方法:

//导入concurrent包下面的AtomicInteger内容
import java.util.concurrent.atomic.AtomicInteger;

public class TestAtomic {// 测试concurrent包下的AtomicInteger
	public static AtomicInteger i = new AtomicInteger(0);// 所有的线程操作同一个对象
	public static int A = 0;

	public static void main(String[] args) throws InterruptedException {
		System.out.println("i累计前"+TestAtomic.i+",A累计前:"+TestAtomic.A);
	Thread t0=	new Thread(
		new Runnable(){

			@Override
			public void run() {
				for(int j=0;j<100000;j++)
				{
					
					TestAtomic.A++;
					TestAtomic.i.getAndIncrement();
				}		
			}
	});
	Thread t1=	new Thread(
				new Runnable(){

					@Override
					public void run() {
						for(int j=0;j<100000;j++)
						{
							
							TestAtomic.A--;
							TestAtomic.i.decrementAndGet();
						}		
					}
			});
	t0.start();
	t1.start();
	t0.join();
	t1.join();
		
		System.out.print("i累计后"+TestAtomic.i+",A累计后:"+TestAtomic.A);
	
}
}


上述代码的运行结果为:

i累计前0,A累计前:0

i累计后0,A累计后:24531

从上述代码中我们可以看出,变量i保证了结果的正确性,原因在于i采用的是AtomicInteger 属性,变量具备原子性,从而保证了该变量是线程安全的。

(2)对已经new出来的某个变量进行修改,保证其原子性。

AtomicIntegerFieldUpdater使用最重要的在于其构造函数,我们可以在其api文件中查看

public static AtomicIntegerFieldUpdaternewUpdater(Class tclass,

                                                         String fieldName)

使用方法:

private AtomicIntegerFieldUpdater

        atomicIntegerFieldUpdater = AtomicIntegerFieldUpdater.newUpdater(

                Details.class, "numberTimesInvoked" );

详细使用代码:

import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;

/**
 * volatiles cannot be used directly in operations that do x = x + 1 for
 * numbers can be skipped or duplicated when there are multiple threads
 * involved.
 * 

* Hardware supports Atomic Compare And Swap operations. CAS java classes * like AtomicInteger can use this feature of the hardware to ensure that * a "x = x + 1" like operation is atomic. *

* However AtomicInteger is significantly more resource intensive than a simple * volatile. If there are many instances of a class which has an AtomicInteger * this increase in resource over a volatile can be significant. *

* The AtomicIntegerFieldUpdater comes to the rescue - it can be registered * with a volatile variable of a class and can then be used on multiple * instances of the class. * * If there are 1000s of instances of a class which would ordinarily have * AtomicInteger this can be a big saving. * * AtomicIntegerFieldUpdater is able to update a volatile field of an object * atomically. * * @author John Dickerson */ public class AtomicIntegerFieldUpdaterCounter { // AtomicIntegerFieldUpdater is registered with Details.class so that it // knows it will later be updating the volatile field called // numberTimesInvoked //步骤1 构造方法 private AtomicIntegerFieldUpdater

atomicIntegerFieldUpdater = AtomicIntegerFieldUpdater.newUpdater( Details.class, "numberTimesInvoked" ); /** * Diferent threads can call this method to update the volatile field of * an instance of Details * * @param details Details object which has the volatile field called * "numberTimesInvoked" in it. * * @return the value of the counter after it has been incremented by one */ //步骤2 对AtomicIntegerFieldUpdater修饰的变量进行操作 public int addOne( Details details ){ // performs a "x = x + 1" style atomic operation //return atomicIntegerFieldUpdater.addAndGet( details, 1 ); return this.atomicIntegerFieldUpdater.getAndIncrement(details); } public int subOne(Details details) { return atomicIntegerFieldUpdater.decrementAndGet(details); } /** * See test class for example of using this class with multiple threads, * some of which are writing to the volatile field and some which are * reading from the volatile field * @throws InterruptedException */ public static void main(String[] args) throws InterruptedException { final AtomicIntegerFieldUpdaterCounter atomicIntegerFieldUpdaterCounter = new AtomicIntegerFieldUpdaterCounter(); // This call would ordinarily be made by many other threads final Details d=new Details(); System.out.print("对象d的变量numberTimesInvoked累计前:"+d.getNumberTimesInvoked()); System.out.println(",A累计前:"+TestAtomic.A); Thread t0= new Thread( new Runnable(){ @Override public void run() { for(int j=0;j<100000;j++) { atomicIntegerFieldUpdaterCounter.addOne(d); TestAtomic.A++; } } }); Thread t1= new Thread( new Runnable(){ @Override public void run() { for(int j=0;j<100000;j++) { TestAtomic.A++; atomicIntegerFieldUpdaterCounter.subOne(d); } } }); t0.start(); t1.start(); t0.join(); t1.join(); System.out.print("对象d的变量numberTimesInvoked累计后:"+d.getNumberTimesInvoked()); System.out.println(",A累计后:"+TestAtomic.A); } }


/**
 * @author John Dickerson
 */
public class Details {

    volatile int numberTimesInvoked;

    public int getNumberTimesInvoked() {

        return numberTimesInvoked;
    }

    public void setNumberTimesInvoked(int numberTimesInvoked) {

        this.numberTimesInvoked = numberTimesInvoked;
    }
}



运行结果如下:

对象d的变量numberTimesInvoked累计前:0,A累计前:0

对象d的变量numberTimesInvoked累计后:0,A累计后:199947

从上述代码中我们可以看出,新创建的:Details d=newDetails();对象d的变量numberTimesInvoked,经过this.atomicIntegerFieldUpdater.getAndIncrement(d); 构造后成了一个线程安全的变量。

你可能感兴趣的:(并发编程学习)