高级并发编程学习-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 <U> AtomicIntegerFieldUpdater<U>newUpdater(Class<U> tclass,

                                                         String fieldName)

使用方法:

private AtomicIntegerFieldUpdater<Details>

        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.
 * <p>
 * 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.
 * <p>
 * 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.
 * <p>
 * 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<Details>
        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); 构造后成了一个线程安全的变量。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值