• Java中的线程安全问题


    线程安全主要体现在 原子性 可见性 有序性

    原子性

    什么是原子性

    原子性指的是一个或多个操作在CPU中不会被中断的特性

    原子性问题产生的原因

    原子性出现问题的原因在于 CPU切换时间片导致线程切换

    如何解决原子性问题

    使用 JDK 提供的Atomic开头的原子类、synchronizedLOCK。

    Atomic类采用了CAS方法来保证原子性

    1. java语言CAS底层如何实现?

    利用unsafe提供的原子性操作方法。

    2.什么是 ABA问题?怎么解决?(ABA问题是CAS机制的缺点)

    当一个值从A变成B,又更新回A,普通CAS机制会误判通过检测。

    利用版本号比较可以有效解决ABA问题。

    CAS的缺点

    1) CPU开销过大

    在并发量比较高的情况下,如果许多线程反复尝试更新某一个变量,却又一直更新不成功,循环往复,会给CPU带来很到的压力。

    2) 不能保证代码块的原子性

    CAS机制所保证的知识一个变量的原子性操作,而不能保证整个代码块的原子性。比如需要保证3个变量共同进行原子性的更新,就不得不使用synchronized了。

    3) ABA问题

    这是CAS机制最大的问题所在。

    特别的是

    在JAVA1.6以上版本,synchronized转变为重量级锁之前,也会采用CAS机制。

    可见性

    什么是可见性

    一个线程对共享变量的修改,另外一个线程能够立刻看到。

    可见性问题产生原因

    CPU缓存与内存导致的可见性问题。

    如何解决可见性问题

    使用volatile关键字保证可见性。

    Volatile关键字

    volatile关键字的目的是告诉虚拟机:

    volatile修饰的变量,在每个读操作(load操作)之前都加上Load屏障,强制从主内存读取最新的数据。每次在assign赋值后面,加上Store屏障,强制将数据刷新到主内存。

    每次访问变量时,总是获取主内存的最新值;

    每次修改变量后,立刻回写到主内存。

    volatile与synchronized的区别:

    volatile本质是在告诉jvm当前变量在寄存器中的值是不确定的,需要从主存中读取;synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住q
    volatile仅修饰变量;synchronized则可以修饰变量、方法、代码块
    volatile仅保证可见性;synchronized则可以保证可见性和原子性
    volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞
    volatile修饰的变量会禁止指令重排序,因而程序不会被编译器优化;synchronized修饰的变量没有禁止指令重排序,因而程序可以被编译器优化

     

    有序性

    什么是有序性

    程序执行代码的顺序按照代码的顺序

    有序性问题产生的原因

    Cpu对于指令优化排序,所带来的有序性问题

    怎么解决有序性问题

    使用volatile关键字禁止指令重排;遵循happens-before原则。

    内存屏障保证可见性

    volatile修饰的变量,在每个读操作(load操作)之前都加上Load屏障,强制从主内存读取最新的数据。每次在assign赋值后面,加上Store屏障,强制将数据刷新到主内存。

  • 相关阅读:
    怎么样学习pmp知识?
    黑客赏金猎人平台之Immunefi
    【数据库范式】实际案例分析
    C#A类调用B类的方法,在方法中更新B类的控件
    uboot源码——内核启动分析
    Vue----单文件组件
    java心理健康测评与咨询系统springboot+ssm
    注解(Annotation)
    LeetCode //C - 9. Palindrome Number
    如何选择适合企业需求的企业知识库管理软件
  • 原文地址:https://blog.csdn.net/m0_66605858/article/details/126875679