Offer

Java-学习日记(Atomic,Volatile)

很早之前在公司就看到了atomicInteger,atomicLong这些变量了,一直不明白是什么意思,今天花了点时间了解下。

volatile:

先从volatile开始讲起,volatile是多线程中会使用的关键字,volatile不加锁(即不会线程阻塞,但不安全),但保证了可见性(一个线程修改,立即刷新到主内存,对其他线程可见)和禁止指令重排序。但是这样依然对存在一个问题,就是多线程时候来不及刷新到主内存中,新线程就获取到了旧数据。例如下面代码:

错误原因:有的线程已经把a进行了加1操作,但是还没来得及重新刷入到主存,其他的线程就重新读取了旧值。因为才造成了错误

package atomic;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @ProjectName: AtomicIntegerTest
 * @Package: atomic
 * @Description:
 * @Author: huyuqiao
 * @CreateDate: 2020/9/21 14:25
 */
//Volatile:无法保证最后a结果一定是50
//AtomicInteger:虽然最后顺序不一样,但是最终a一定是50
public class AtomicIntegerTest {
//    private static volatile int a = 0;
    static AtomicInteger a = new AtomicInteger();
    public static void main(String[] args){  
        AtomicIntegerTest atomicIntegerTest = new AtomicIntegerTest();
        Thread[] threads = new Thread[5];
        for (int i = 0; i < 5; i++) {
            threads[i] = new Thread(() ->{
                try{
                    for (int i1 = 0; i1 < 10; i1++) {
//                        System.out.println(a++);
                        System.out.println(a.incrementAndGet());
                        Thread.sleep(500);
                    }
                } catch (Exception e){
                    e.printStackTrace();
                }
            });
            threads[i].start();
        }
    }
}

atomicInteger

上面代码中atomicInteger却保证了数据的完整性,原因就在于内部CAS原理(compare and swap)

CAS 即比较并替换,实现并发算法时常用到的一种技术。CAS操作包含三个操作数——内存位置、预期原值及新值。执行CAS操作的时候,将内存位置的值与预期原值比较,如果相匹配,那么处理器会自动将该位置值更新为新值,否则,处理器不做任何操作。

但是这样会有一个ABA问题,就是虽然你保证了数据最终一定一直,但是无法保证数据中途会被修改,即ABA问题(变量A->B->A中途会被修改)

ABA问题解决办法:解决使用AtomicStampReference.getstamp标记更新次数,若没被更新,则正确,否则报错。

面试问题:并发编程(原子性、可见性、一致性)

posted @ 2020-09-21 19:04  Empirefree  阅读(215)  评论(0编辑  收藏  举报