原子变量和CAS算法以及ConcurrentHashMap

Posted xbfchder

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了原子变量和CAS算法以及ConcurrentHashMap相关的知识,希望对你有一定的参考价值。

1.首先做一个测试:i++。输出结果为10,因为在底层实现的时候会引入一个临时变量具体为:

 1 public static void main(String[] args) 
 2         //i++测试:
 3         int i=10;
 4         i=i++;
 5         System.out.println(i);
 6         /*
 7         *底层原理:
 8         _temp = i ;
 9         i = i + 1 ;
10         i = _temp ;
11         * */
12     

所以i++就是一个非原子性操作,采用多线程再次测试:测试结果中会因为i++的非原子性操作带来读写不一致问题。比如:1,3,2,2,4,5,6,7,8,9序列的出现。两个2的出现就说明了,两个线程在同时从主存中读取,和进行加一操作时出现的不一致问题,那么可以用Volatile来解决这个不一致问题吗?不行。因为,这是一个非原子性操作。

 1 public class TestAtomicDemo 
 2     public static void main(String[] args) 
 3 
 4         Testi testi = new Testi();
 5 
 6         for (int i = 0; i < 10; i++) 
 7             new Thread(testi, String.valueOf(i)).start();
 8         
 9     
10 
11 class Testi implements Runnable
12     int a=1;
13     @Override
14     public void run() 
15         try 
16             Thread.sleep(1000);
17          catch (InterruptedException e) 
18             e.printStackTrace();
19         
20         System.out.println(Thread.currentThread().getName()+": "+getA());
21     
22     public int getA() 
23         return a++;    
24     
25 

2.Java并发包(java.util.concurrent)的主要实现机制:

采用Volatile保证内存的可见性;

采用CAS(Compare And Swap)算法保证数据的原子性。

 

3.乐观锁(CAS算法)和悲观锁(synchronized):

Synchronized就是一种悲观锁,因为它总是假设最坏的情况,每次去拿数据都会认为别人会修该,所以每次都会加锁,效率较低。

乐观锁其实是一种思想,它具体有两个步骤:冲突检测和数据更新。所以它不会每次访问都进行加锁控制,只是在进行更新操作时才进行冲突检测和数据更新,适合用于读操作较多的程序,因此大大提高了吞吐量。其实现方式比较典型的就是CAS算法。当多个线程同时更新同一个变量时,只会有一个线程成功修改,其他的都会失败,更新失败的线程不会被挂起,而是被告知在这次竞争中失败了,并可以再次尝试。

4.CAS(Compare And Swap)原理: 

首先涉及三个操作数:

内存值(V)--->首次读取内存中的值;

预估值(A)--->再一次读取的内存中的值;

更新值(B)--->新值;

每次在进行更新操作时,当且仅当V==A(内存值和预期值相等时),后 V=B(将内存值更新为B),否则不进行任何操作。

CAS是一种非阻塞算法的常见实现,JUC性能因此大大提升。

 1 //模拟CAS算法:
 2 public class TestCAS 
 3     public static void main(String[] args) 
 4         Cas cas = new Cas(10);
 5         for (int i = 0; i < 10; i++) 
 6             new Thread(() -> 
 7                 //10个线程都进行对数据的更新操作
 8                 int expectedValue = cas.getValue();  //更新前获得预期值
 9                 boolean b = cas.CompareTest(expectedValue, (int) Math.random());
10                 System.out.println(b);
11 
12             ).start();
13         
14     
15 
16 class Cas
17     /*
18     * 内存值;预期值;新值。
19     * */
20 
21     int value;  //内存值
22 
23     public synchronized int getValue() 
24         return value;
25     
26 
27     public Cas(int value)    //构造方法
28         this.value = value;
29     
30 
31     //比较交换,并将内存值返回
32     public int CompareSwap(int expectedValue,int newValue)
33         int oldValue=value;  //获得内存值
34         if(oldValue==expectedValue)
35             value=newValue;
36         
37         return oldValue;
38     
39 
40     //检测是否更新成功
41     public boolean CompareTest(int expectedValue,int newValue)
42         boolean flag=false;
43         if(expectedValue==CompareSwap(expectedValue,newValue))
44             //判断预期值和内存值是否相等->更新是否成功
45             flag=true;
46         
47         return flag;
48     
49 

CAS算法的ABA问题(当前线程的CAS操作无法分辨,值是否已经发生过变化):解决方法->在修改值的同时增加一个时间戳,只有当预期值和时间戳都相同时才进行修改。

 

以上是关于原子变量和CAS算法以及ConcurrentHashMap的主要内容,如果未能解决你的问题,请参考以下文章

原子变量与CAS算法

原子变量与CAS算法

2.原子变量 CAS算法

volatile关键字与内存可见性&原子变量与CAS算法

并发编程__原子变量

聊聊并发——CAS算法