并发编程之___请谈谈你对volatile的理解?

  • 三个特性:volatile是JVM提供的轻量级线程同步机制。

    • 可见性

      • 根据JMM模型,两个线程同时操作同一个变量时,当一个线程对其进行修改后,那么可以保证另一个线程可见。

        • JMM概念:

          • JMM本身是一种抽象的概念,并不真实存在的它描述的是一组规则或规范,通过这组规范定义程序中各个变量(包括实例字段,静态字段,和构成数组对象的元素)的访问方式。

        • JMM关于同步的规定:

          • 1、线程解锁前,必须把共享变量的值刷新回主内存。

          • 2、线程加锁前,必须读取主内存的最新值到自己的工作内存。

          • 3、加锁解锁是同一把锁。

      • 说明:

        • 由于JVM运行的实体是线程,而每个线程创建时JVM都会为其创建一个工作内存(也成为栈空间),工作内存是每个线程的私有数据区域,而Java内存模型中规定所有的变量都存储在主内存,主内存是共享内存区域,所有线程都可以访问。但线程对变量的操作(读取或赋值)必须在工作内存中进行,首先要将变量从主内存拷贝到自己的工作空间,然后对变量进行操作,操作完成后再将变量写回主内存。不能直接操作主内存中的变量,各个线程的工作内存中存储着主内存的变量副本拷贝,因此不同的线程间无法访问对方的工作内存,线程间的通信(传值)必须通过主内存来完成。

    • 有序性

      • 说明

        • 计算机执行程序时,为了提高性能,编译器和处理器会对指令做重排序,如下:

          • 因此,处理器在进行重排序时,就要考虑到指令之间的数据依赖性。

          • 因此多线程程序中,线程交替执行,两个线程使用的同一变量是否一致无法确定。

        • 举例:

          • 1、执行顺序:1 2 3 4   2 3 4 1   4 3 2 1都有可能

          • 2、重排序之后结果改变

          • 如下案例:因为指令重排,可能导致先执行语句2,但是语句1还没执行,就执行了语句3,导致结果出错。

    • 不保证原子性

      • 什么叫原子性?

        • 原子操作:不可分割的最小操作单位

          • a = 1;原子性

          • c ++; 不是原子操作

            • c = c + 1;

            • ①从主物理内存得到c的值

            • ②将c得值+1

            • ③将新的值赋值给c,并写回主物理内存

        • 因此并发编程中就要保证c++的原子操作

      • 如何解决保证原子性?

        • 加synchronized

        • AtomicInteger

  • 禁止指令重排本质?通过cpu指令,设置内存屏障。

  • DCL机制不一定线程安全?为什么?如何解决:加volatile关键字修饰

package com.coinker.volatile1;





import java.util.stream.Stream;





public class SingletonDemo {





    private static SingletonDemo singleton = null;





    public SingletonDemo() {

        System.out.println(Thread.currentThread().getName()+ "      单例模式被创建了。。。。。");

    }





    // DCL, 双重检查的方式

    public static SingletonDemo getSingleton() {

        if (singleton == null) {

            synchronized (SingletonDemo.class) {

                if (singleton == null) {

                    singleton = new SingletonDemo();

                }

            }

        }

        return singleton;

    }





    public static void main(String[] args) {

        for (int i = 0; i < 10; i++) {

            new Thread(() -> {

                SingletonDemo.getSingleton();

            }, String.valueOf(i)).start();

        }

    }





}
原创文章 63 获赞 48 访问量 8万+

猜你喜欢

转载自blog.csdn.net/csp_6666/article/details/102805241