关于synchronized-reentrantlock-volatile学习总结1.0
synchronized 是什么#synchronized是 java 提供的原子性内置锁实现基本的同步机制不支持超时非公平不可中断不支持多条件基于 JVM 的 Monitor监视锁机制实现主要解决的是多个线程之间的访问资源的同步性可以保证被它修饰的方法或者代码块在任意时刻只有一个线程执行以及保证原子性可见性有序性监视器锁Monitor是 JVM 内置的锁机制开发者无法直接操作 Monitor只能通过synchronized间接使用它。Monitor 的获取与释放对开发者是不可见的由 JVM 自动管理synchronized还是排它锁当一个线程获得锁之后其他线程就必须等到该线程释放锁之后才能获得锁由于java中的线程和操作系统原生线程一一对应线程被阻塞或者唤醒的时候会从用户态转换为内核态这种转换非常消耗性能。synchronized 的可重入性#synchronized是可重入的每获取一次锁计数器加一释放锁时计数器减一直到计数器为 0锁才会真正释放。ReentrantLockReentrantLock是 JUCjava.util.concurrent.locks提供的一个可重入锁、可中断、公平锁/非公平锁任选的显式锁Explicit LockReentrantLock 锁模式#非公平锁默认#获取锁的时候会“插队”性能高吞吐量大公平锁#FIFO先来先获取锁但是性能比非公平锁低CopyReentrantLock lock new ReentrantLock(true); // true 公平锁ReentrantLock的能力#ReentrantLock底层实现主要是依赖于抽象类AbstractQueuedSynchronizer(AQS)该类提供了基本同步机制的框架其中包含了队列状态值等。1、tryLock() – 尝试获得锁不等待#Copyif (lock.tryLock()) {try { ... } finally { lock.unlock(); }} else {System.out.println(获取锁失败);}作用防止线程永久等待 → 适合高性能场景比如秒杀系统2、tryLock(timeout) – 超时获取锁#Copyif (lock.tryLock(2, TimeUnit.SECONDS)) {try { ... } finally { lock.unlock(); }}作用避免长时间等待适用于读写混用、高并发业务。3、lockInterruptibly – 可中断获取锁#Copytry {lock.lockInterruptibly();try { ... } finally { lock.unlock(); }} catch (InterruptedException e) {System.out.println(线程被中断放弃等待锁);}作用在等待锁期间可取消任务适用于死锁检测等场景。4、多条件队列 – Condition#相比于synchronized只有一个wait-set而ReentrantLock可以创建多个ConditionCopyCondition condition lock.newCondition();作用实现更复杂的线程通信比如生产者 / 消费者 多条件控制。Synchronized VS. ReentrantLock能力synchronizedReentrantLock可重入✔✔公平锁✘✔可选非阻塞尝试✘tryLock() ✔可中断获取锁✘lockInterruptibly() ✔超时获取锁✘tryLock(timeout) ✔条件队列1 个 wait-set多个 Condition ✔必须手动释放锁自动必须 unlock()使用场景一般情况用Synchronized就行比较简单比较灵活支持的功能比较多在复杂情况下用volatilevolatile 的作用#主要保证变量的可见性和禁止指令重排优化但是不能保证原子性1、可见性Visibility#多个线程读写共享变量如果不加 volatile线程可能读取到旧值因为线程读的是工作内存副本volatile 让线程每次读取都从主内存读避免线程间由于缓存一致性问题导致的 “看见” 旧值的现象。2、禁止指令重排序ordering#volatile 会插入内存屏障Memory Barrier例如LoadLoadStoreStoreStoreLoad最强从而阻止 JVM 和 CPU 进行重排序Synchronized VS. volatilevolatile 只保证可见性 禁止重排synchronized 保证原子性 可见性 有序性。volatile 是“轻量级读写”synchronized 是“重量级加锁”。对比项volatilesynchronized是否保证原子性❌ 不保证✔ 保证可见性✔ 保证✔ 保证是否禁止指令重排✔ 禁止✔ 禁止通过内存屏障是否会阻塞线程❌ 不会阻塞✔ 可能阻塞等待锁是否适用于复合操作i❌ 不适用✔ 适用性能⭐ 非常快 慢涉及锁竞争底层实现内存屏障 volatile 写入协议监视器锁Monitorenter/monitorexit是否可重入不适用✔ 可重入锁是否能实现临界区保护❌ 不行✔ 可以