• java 可见性简单总结


    Java 可见性

    内存模型

    • 主存
      • 所有线程都可以访问
    • 本地内存
      • 每个线程私有的内存
    - java 的所有变量都存储在主内存中
    - 每个线程有自己独的工作内存,保存了该线程使用到的变量副本,是对主内存中变量的一份拷贝
    - 每个线程不能访问其他线程的工作内存,线程间变量传递需要通过主内存来完成
    - 每个线程不能直接操作主存,只能把主存的内容拷贝到本地内存后再做操作(这是线程不安全的本质),然后写回主存
    

    可见性的方法

    volatile

    这种方式可以保证每次取数直接从主存取

    它只能保证内存的可见性,无法保证原子性

    它不需要加锁,比 synchronized 更轻量级,不会阻塞线程

    不会被编译器优化

    然而要求对这个变量做原子操作,否则还是会有问题

    虽然 volatile 是轻量级,但是它也需要保证 读写的顺序不乱序,所以可以有优化点,比如在单例实现方式中的双重校验中,使用 临时变量 降低 volatile 变量的访问。

    synchronized

    Synchronized 能够实现原子性和可见性;在 Java 内存模型中,synchronized规 定,线程在加锁时,先清空工作内存 → 在主内存中拷贝最新变量的副本到工作内存 → 执行完代码 → 将更改后的共享变量的值刷新到主内存中 → 释放互斥锁。

    所以如果无法用 volatile 做可见性,则可以考虑用 synchronized 可以做可见性的保证

    AtomicXXX

    jdk 提供了很多原子类型,这种类型的基本原理总结起来,volatile + unsafe 的 Compare and Swap,这种 Unsafe 操作并不推荐在自己的代码中使用,因为各 JDK 版本在这里变化较大,有可能升级 JDK 时造成各种问题。而且也要保证自己能够用好。

    LongAdder

    待补充

  • 相关阅读:
    Java——spring入门
    Java日志管理之logback
    Java之MyBatis
    Java之JDBC
    Java核心类——BigDecimal
    Java核心类——BigInteger
    Java核心类——枚举类
    Java核心类——JavaBean
    Java核心类——包装类型
    Java核心类——StringJoiner
  • 原文地址:https://www.cnblogs.com/43726581Gavin/p/9066080.html
Copyright © 2020-2023  润新知