两个例子解释线程的可见性和原子性问题

本文深入探讨了多线程环境下常见的线程安全问题——可见性和原子性,并提供了具体的解决方案。通过使用volatile关键字确保变量在多线程间的可见性,以及利用CAS操作实现原子性更新,有效避免了并发编程中的数据不一致问题。

多线程情况下,会出现两种线程安全的问题:可见性和原子性问题。具体针对这两种多线程情况下出现问题的解决方案如下:
(1)可见性:

//用volatile关键字屏蔽CPU缓存和指令重排序,保证线程可见性
public class VolatileTest {
    boolean flag = true;//用这个会导致thread1线程不能读到被修改的flag值,thread1线程的循环永远不会结束
//    volatile boolean flag = true;//用这个thread1线程可以读到被修改的flag值
    int i = 0;
    public static void main(String[] args) throws InterruptedException {
        VolatileTest volatileTest = new VolatileTest();
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                while (volatileTest.flag) {//当flag为false时循环结束
                    volatileTest.i++;
                }
                System.out.println("循环结束\n");
                System.out.println("i为:"+volatileTest.i+"\n");
                System.out.println("flag为:" + volatileTest.flag + "\n");
            }
        });
        thread1.start();
        Thread.sleep(3000);//休眠3秒
        volatileTest.flag= false;//修改flag值
        System.out.println("flag为:" + volatileTest.flag + "\n");
    }
}

(2)原子性:

//利用CAS操作保证原子性,是一种乐观锁的思想(需要注意的是因为CAS需要自旋,可能会占用大量CPU)
public class AtomicTest {
    public static void main(String[] args) {
        /**
         * 基本的原子操作
         */
        AtomicInteger atomicInteger = new AtomicInteger(5);
        atomicInteger.compareAndSet(5,6);
        System.out.println(atomicInteger.get());
        AtomicIntegerArray array = new AtomicIntegerArray(3);
        array.set(1,12);
        array.compareAndSet(1,12,13);
        System.out.println(array.get(1));
        /**
         * 累加器
         */
        LongAccumulator accumulator = new LongAccumulator((x,y)->{
            //这里写累加的逻辑(x的累加器)
            System.out.println("x:"+x+",y:"+y);
            //把x+y的值赋给x了
            return x+y;
        },0);//identity是x的初始值
        for (int i=0;i<3;i++){
            accumulator.accumulate(1);//这里相当于每次累加1,这里是y的值
        }
        System.out.println("结果为:"+accumulator.get());
        /**
         * 带版本号的(解决ABA问题)
         */
        int stamp = 0;//版本号
        AtomicStampedReference<Integer> item = new AtomicStampedReference<Integer>(0,stamp);
        item.compareAndSet(0,2,0,stamp+1);
        System.out.println("最新的值为:"+item.getReference()+"\n");
        System.out.println("最新的版本为:"+item.getStamp()+"\n");
    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值