• 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屏障,强制将数据刷新到主内存。

  • 相关阅读:
    最新一站式AI创作中文系统网站源码+系统部署+支持GPT对话、Midjourney绘画、Suno音乐、GPT-4o文档分析等大模型
    回溯算法解决N皇后问题以及个人理解
    CentOS6.5 离线安装python3.9.9 openssl-1.1.1
    2022年全国最新消防设施操作员(中级消防设施操作员)题库及答案
    2024/2/29 备战蓝桥杯 6-1 二分
    python画图画字-turtle
    43.集群调优策略—Index 写调优-2
    LeetCode每日一题——2678. Number of Senior Citizens
    一篇文章快速教你如何搭建数据驱动自动化测试框架?
    反转字符串II
  • 原文地址:https://blog.csdn.net/m0_66605858/article/details/126875679