美文网首页
[并发] 4 线程安全性-可见性

[并发] 4 线程安全性-可见性

作者: LZhan | 来源:发表于2019-11-03 21:36 被阅读0次

1.共享变量在线程间不可见的原因

<1> 线程交叉执行
<2> 重排序结合线程交叉执行
<3> 共享变量更新后的值没有在工作内存与主内存间及时更新

2.synchronized

规定1:线程解锁前,必须把共享变量的最新值刷新到主内存
规定2:线程加锁时,将清空工作内存中共享变量的值,从而使用共享变量时需要从主内存中重新读取最新的值(注意:加锁和解锁是同一把锁)

3.volatile

通过加入内存屏障禁止重排序优化来实现,即

  • 1 对volatile变量写操作时,会在写操作后加入一条store屏障指令,将本地内存中的共享变量值刷新到主内存
  • 2 对volatile变量读操作时,会在读操作前加入一条load屏障指令,从主内存中读取共享变量

volatile应用于计数问题

public class CountExample4 {

    //请求总数
    public static int clientTotal=5000;

    //同时并发执行的线程数
    public static int threadTotal=200;


    public static volatile int count=0;

    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService= Executors.newCachedThreadPool();
        final Semaphore semaphore=new Semaphore(threadTotal);
        final CountDownLatch countDownLatch=new CountDownLatch(clientTotal);
        for (int i=0;i<clientTotal;i++){
            executorService.execute(()->{
                try{
                    semaphore.acquire();
                    add();
                    semaphore.release();
                }catch (Exception e){
                    log.error("exception",e);
                }
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        executorService.shutdown();
        log.info("count:{}",count);
    }

    private static  void add(){
        count++;
    }

}

此时,并不能保证最后的结果为5000,因为在执行count++时,假设有两个线程,
第一步读取count值,都是从主内存中获取值,两个线程没有问题;
第二步,对count值进行自增操作;
第三步,将最新的count值写回到主内存中;
如果两个线程同时执行2,3步,可能会减少count++的次数。

所以volatile不适用计数场景,不具备原子性。
volatile使用的场景:
1.作为状态标记量
(对变量的写操作不依赖于当前值;该变量没有包含在具有其他变量的式子中)

image.png
2.还适用double check场景

相关博客链接:https://www.jianshu.com/p/ccfe24b63d87

相关文章

  • [并发] 4 线程安全性-可见性

    1.共享变量在线程间不可见的原因 <1> 线程交叉执行<2> 重排序结合线程交叉执行<3> 共享变量更新后的值没有...

  • 【Java并发编程实战】-----线程基本概念

    并发一些基本的概念 共享、可变、线程安全性、线程同步、原子性、可见性、有序性 共享内存 每个线程表示一条单独的执行...

  • 线程基本概念

    1、基本概念 在学习Java并发之前我们需要先理解一些基本的概念:共享、可变、线程安全性、线程同步、原子性、可见性...

  • Java并发

    本文回顾并发知识,划出关键部分, 并发基础 “共享”、“可变“、“可重入”,线程之间对象“可见性”是并发的基础。 ...

  • 2019年Java并发精选面试题,哪些你还不会?(含答案和思维导

    Java 并发编程 1、并发编程三要素? 2、实现可见性的方法有哪些? 3、多线程的价值? 4、创建线程的有哪些方...

  • 02|Java内存模型

    可见性、原子性、有序性是并发问题的三个关键因素。 可见性:一个线程对共享变量的修改,另外一个线程能够立刻看到。 可...

  • 原子性,可见性,有序性

    转载自:并发之可见性并发之原子性并发之有序性 01 可见性的阐述 可见性 的定义是:一个线程对共享变量的修改,另外...

  • 并发编程-安全性、活跃性以及性能问题

    一、安全性问题 并发 Bug 的三个主要源头:原子性问题、可见性问题和有序性问题。理论上线程安全的程序,就要避免出...

  • Android面试遇到的问题之并发集合

    并发集合类如下: ConcurrentHashMap 和 CopyOnWriteArrayList 提供线程安全性...

  • Java 多线程可见性

    在现代操作系统上编写并发程序时,除了要注意线程安全性(多个线程互斥访问临界资源)以外,还要注意多线程对共享变量的可...

网友评论

      本文标题:[并发] 4 线程安全性-可见性

      本文链接:https://www.haomeiwen.com/subject/efqlbctx.html