多线程只Volatile和原子变量

Volatile使用常见误区

Volatile 使用最常见的误区就是并发 i++, i++是依赖当前 i 值,如果多个线程同时给当前值+1,可能同时返回,导致与预期值不符合。

比如两个线程同时读到 i 的当前值8,都进行加一,然后写回,最终 i 的结果是 9,而不是我们期待的10,丢失了更新。那么原子变量的引入就是针对volatile的这个缺陷的!!

原子变量的修改操作允许它依赖于当前值,所以说”原子变量“是比volatile的语义稍微强化一点!他不仅具有volatile的可见性,同时对原子变量的修改可以依赖于当前值。

原子变量的实现,使用了 volatile和unsafe方法, volatile保证可见性,unsafe保证原子性

代码测试

public class VolitaileTest {
    private static volatile int i = 0;
    private static AtomicInteger count = new AtomicInteger(0);

    private static class Plus implements Runnable{
        @Override
        public void run() {
            i++;
            count.getAndIncrement();
        }
    }

    public static void main(String[] args) {
        for (int i1 = 0; i1 < 1000; i1++) {
            Thread t = new Thread(new Plus());
            t.start();
        }
        System.out.println(i);
        System.out.println(count);
    }
}

输出

999
1000

可以看到,在并发场景下,volatile++会出现不符合预期值的情况,但是 原子变量是没问题的。

实现三个线程有序输出

有三个线程,并发情况下,按顺序调用。

  1. join() : 主线程看到 子线程的join() 方法,会停止等待子线程执行完

    				fir.start();
            fir.join();
            sec.start();
            sec.join();
            thr.start();
    
  2. Executors.newSingleThreadExecutor() 创建单线程池,挨个执行

     				ExecutorService executorService = Executors.newSingleThreadExecutor();
            executorService.submit(fir);
            executorService.submit(sec);
            executorService.submit(thr);
            executorService.shutdown();
    
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值