Java 并发知识点(1)

并发问题出现的原因,如何解决?

原因:为了平衡CPU、内存、I/O 设备的速度差异

  • CPU 增加了缓存,以均衡与内存的速度差异(缓存与主存数据可能不一致)-- 可见性问题
  • 操作系统增加了进程、线程,以分时复用 CPU,进而均衡 CPU 与 I/O 设备的速度差异(多线程切换,非原子操作被拆分执行)-- 原子性问题
  • 编译程序优化指令执行次序,使得缓存能够得到更加合理地利用。-- 有序性问题
  1. 原子性:
    Java内存模型只保证了基本读取和赋值是原子性操作,如果要实现更大范围操作的原子性,可以通过synchronized和Lock来实现。
    synchronized和Lock能够保证任一时刻只有一个线程执行该代码块,从而保证了原子性。

  2. 可见性:
    volatile:当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值。
    通过synchronized和Lock也能够保证可见性,synchronized和Lock能保证同一时刻只有一个线程获取锁然后执行同步代码,并且在释放锁之前会将对变量的修改刷新到主存当中。因此可以保证可见性。

  3. 有序性:
    volatile关键字来保证一定的“有序性”,它会保证修改的值会立即被更新到主存。
    通过synchronized和Lock来保证有序性,synchronized和Lock保证每个时刻是有一个线程执行同步代码,相当于让线程顺序执行同步代码,由此保证了有序性。
    JMM是通过Happens-Before 规则来保证有序性的。
    Happens-Before :如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须存在 happens-before 关系。这里的两个操作既可以是在一个线程之内,也可以是在不同线程之间。 happens-before 规则如下:

    • 程序顺序规则:一个线程中的每个操作,happens- before 于该线程中的任意后续操作。
    • 监视器锁规则:对一个监视器锁的解锁,happens- before 于随后对这个监视器锁的加锁。
    • volatile 变量规则:对一个 volatile 域的写,happens- before 于任意后续对这个 volatile 域的读。
    • 传递性:如果 A happens- before B,且 B happens- before C,那么 A happens- before C。

    ** 两个操作之间具有 happens-before 关系,并不意味着前一个操作必须要在后一个操作之前执行!happens-before 仅仅要求前一个操作(执行的结果)对后一个操作可见,且前一个操作按顺序排在第二个操作之前(the first is visible to and ordered before the second)**

线程安全实现思路

  1. 互斥同步(阻塞同步):synchronized 和 ReentrantLock。悲观锁策略,每次都加锁->用户态、内核态转换->维护锁计数器->检查被阻塞线程是否唤醒等

  2. 非阻塞同步:

  • CAS ,乐观锁
  • AtomicInteger 等原子类
  1. 无同步方案
  • 栈封闭 线程私有变量,只有当前线程操作
  • 线程本地存储 ThreadLocal

线程状态与流转

对应类,java.lang.Thread.State
新建(New):创建后未启动
可运行(Runnable):可能正在运行或等待执行
阻塞(Blocking):等待获取排它锁
等待(Waiting):等待其他线程获取
限期等待(Timed Waiting): Thread.sleep() 或Object.wait()
死亡(Terminated):线程结束
线程装填

线程状态流转

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值