并发编程 — 并发数据类型


并发编程系列文章:
      初解线程池:http://ray-yui.iteye.com/blog/2072463
      详解线程池:http://ray-yui.iteye.com/blog/2075311
      并发数据类型:http://ray-yui.iteye.com/blog/2080454
      并发数据结构:http://ray-yui.iteye.com/blog/2084202


      在并行环境中,同步(锁)操作是实现真正并行的最大敌人,而且大量的锁竞争严重消耗了系统资源,但在开发当中不能避免多条线程对共享变量的修改,JDK1.5后为我们提供了一组实现了无锁算法(CAS算法)的类,他们分别包装了Integer,Long,Boolean和Integer,Long对应的数组类型


AtomicInteger(Long)核心方法:


public final int get() 获取当前值   
public final void set(int newValue) 设置当前值   
public final int getAndSet(int newValue) 设置新值并返回旧值   
public final boolean compareAmdSet(int expect,int u) 若当前值为expect,设置为u   
public final int getAndIncrement() 当前值加1,返回旧值   
public final int getAndDecrement() 当前值减一,返回旧值   
public final int getAndAdd(int delta) 当前值增加delta,返回旧值   
public final int incrementAndGet() 当前值加1,返回新值   
public final int decrementAndGet() 当前值减1,返回新值   
public final int addAndGet(int delta) 当前值增加delta,返回新值   



其他类或方法请参考JDK帮助文档
AtomicReference
AtomicReferenceArray
AtomicBoolean
AtomicInteger
AtomicIntegerArray
AtomicLong
AtomicLongArray



      我们来看一下CAS算法在AtomicInteger中是如何体现出现到

/**
     * Atomically sets to the given value and returns the old value.
     * 
     * @param newValue
     *            the new value
     * @return the previous value
     */
    public final int getAndSet(int newValue) {
        for (;;) {                   // 死循环不停尝试,直到成功
            int current = get();     // 获取当前值
            // 若当前值未受其他线程影响,设置为新值,否则进入第二次循环
            if (compareAndSet(current, newValue))
                return current;
        }
    }


      在CAS算法当中,首先程序体处于一个无限循环当中,在获取当前值后,使用compareAndSet进行比较,若然其他线程对当值进行修改,compareAndSet將返回false从而进入第二次循环,直到成功.在硬件层面,绝大部分的现代处理器已经支持了原子化的CAS指令,在JDK5.0后JVM已可以使用这个指令来实现并发操作和并发数据结构


      除了Integet和Long等自增类型的原子性操作类外,JDK还提供了更令人心动的类型AtomicReference<V>,他能引用所有的引用类型

public class TestMain {
    @Test
    public void testAtomicReference() throws Exception {
        /*
         * 注意: 
         *      要使用AtomicReference引用的类最好重写equals方法
         *      compareAndSet将会使用 == 来判断对象是否相等
         */

        RayTest test1 = new RayTest();
        RayTest test2 = new RayTest();

        // 初始化 AtomicReference,默认值为test1
        AtomicReference<RayTest> reference = new AtomicReference<RayTest>(test1);

        // 將test1替换为test2
        reference.compareAndSet(test1, test2);

        Assert.assertNotSame(test1, reference.get());
        Assert.assertEquals(test2, reference.get());
    }
}


在CAS算法当中,整个过程无需加锁,无需等待,无锁的操作实际上可以将多条线程的并发冲突处理由应用层面自行决定,从而提升系统的性能,但使用CAS算法的编码复杂度明显地增加,还好JDK已为我们提供了Atomic类让我们直接使用,推荐遇到类似需求直接使用已提供好的工具

你可能感兴趣的:(java,多线程,编程)