码迷,mamicode.com
首页 > 编程语言 > 详细

原子性 CAS算法

时间:2018-12-14 00:57:07      阅读:273      评论:0      收藏:0      [点我收藏+]

标签:ret   bubuko   dex   共享   实现   线程   print   reference   cep   

一、 i++ 的原子性问题

1、问题的引入:

i++ 的实际操作分为三个步骤:读--改--写

实现线程,代码如下:

public class AtomicDemo implements Runnable
{
    private int serialNumber = 0;

    @Override
    public void run()
    {
        try
        {
            Thread.sleep(400);
        }
        catch (InterruptedException e)
        {}
        System.out.println(Thread.currentThread().getName() + ": " + this.getSerialNumber());
    }

    public int getSerialNumber()
    {
        return serialNumber++;
    }
}

测试类,代码如下:

public class AtomicTest
{
    public static void main(String[] args)
    {
        AtomicDemo atomicDemo = new AtomicDemo();
        for (int i = 0; i < 10; i++)
        {
            new Thread(atomicDemo).start();
        }
    }
}

结果如下图所示:

技术分享图片

 

以上的原子性问题可以使用“原子变量”解决;

二、原子变量

在JDK1.5 之后,提供了 java.util.concurrent.atomic 包下提供了常用的原子变量;

 AtomicBoolean、AtomicInteger、AtomicIntegerArray、AtomicIntegerFieldUpdater、AtomicLong、AtomicReference 等

从以上类源码中可以看出:

  (1)变量使用了 Volatile 修饰,保证了内存可见性;

  (2)使用了 CAS(Compare-And-Swap)算法,保证了数据的原子性;

  CAS算法是硬件对于并发操作共享数据的支持;

  CAS 包含了三个操作数:内存值 、预估值 、更新值 ;

    当且仅当内存值等于预估值时,把更新值赋给内存值,否则将不做任何操作;

class AtomicDemo implements Runnable
{
    private AtomicInteger serialNumber = new AtomicInteger();

    @Override
    public void run()
    {
        try
        {
            Thread.sleep(400);
        }
        catch (InterruptedException e)
        {}
        System.out.println(Thread.currentThread().getName() + ": " + this.getSerialNumber());
    }

    public int getSerialNumber()
    {
        return serialNumber.getAndIncrement();
    }
}

 

原子性 CAS算法

标签:ret   bubuko   dex   共享   实现   线程   print   reference   cep   

原文地址:https://www.cnblogs.com/yufeng218/p/10117033.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!