当前位置: 首页 > wzjs >正文

相对于网站根目录的的绝对路径seo网站

相对于网站根目录的的绝对路径,seo网站,扒网站样式,加油站网站建设锁机制 1.锁监视器 在 Java 并发编程中,锁监视器(Monitor) 是对象内部与锁关联的同步机制,用于控制多线程对共享资源的访问。以下是核心要点: 🔒 监视器的核心组成 独占区(Ownership&#xff…

锁机制

1.锁监视器

在 Java 并发编程中,锁监视器(Monitor) 是对象内部与锁关联的同步机制,用于控制多线程对共享资源的访问。以下是核心要点:


🔒 监视器的核心组成

  1. 独占区(Ownership)

    • 一次仅允许一个线程持有监视器(即获得锁)
    • 通过 synchronized 关键字实现
  2. 入口区(Entry Set)

    • 竞争锁的线程队列(未获得锁的线程在此等待)
  3. 等待区(Wait Set)

    • 调用 wait() 的线程释放锁后进入此区域
    • 需通过 notify()/notifyAll() 唤醒

⚙️ 关键操作

操作作用触发条件
synchronized线程尝试获取监视器锁,成功则进入独占区,失败则阻塞在入口区进入同步代码块/方法时
wait()释放锁并进入等待区,线程状态变为 WAITING必须在持有锁时调用 (synchronized 内)
notify()随机唤醒一个等待区的线程(唤醒后需重新竞争锁)必须在持有锁时调用
notifyAll()唤醒所有等待区的线程必须在持有锁时调用

🔄 工作流程示例

public class MonitorDemo {private final Object lock = new Object(); // 锁监视器关联到此对象public void doWork() throws InterruptedException {synchronized (lock) { // 1. 线程进入独占区while (条件不满足) {lock.wait(); // 2. 释放锁并进入等待区}// 3. 执行临界区代码lock.notifyAll(); // 4. 唤醒其他等待线程}}
}

⚠️ 重要规则

  1. 锁绑定对象
    每个 Java 对象(包括 Class 对象)都有一个内置监视器

    synchronized(obj) { ... }  // 使用对象监视器
    synchronized(MyClass.class) { ... }  // 使用类对象的监视器
    
  2. wait/notify 必须持有锁
    未在 synchronized 块中调用会抛出 IllegalMonitorStateException

  3. 虚假唤醒(Spurious Wakeup)
    等待线程可能被随机唤醒(即使未调用 notify),必须用循环检查条件:

    while (!condition) { obj.wait();
    }
    

💡 监视器 vs 显式锁(ReentrantLock)

特性内置监视器ReentrantLock
实现方式JVM 内置JDK 代码实现 (java.util.concurrent)
锁获取隐式获取/释放显式调用 lock()/unlock()
等待条件单一等待队列支持多个 Condition 队列
公平性非公平锁可选公平/非公平模式
中断响应不支持支持 lockInterruptibly()

📌 总结

  • 监视器 = 锁 + 等待队列 + 线程调度机制
  • synchronized 实现锁的互斥访问
  • wait()/notify() 实现线程间协作
  • 经典应用场景:生产者-消费者模型、线程间条件等待

⚠️ 注意:优先使用 java.util.concurrent 包中的高级工具(如 ReentrantLockCondition),它们提供更灵活的同步控制,能避免许多内置监视器的限制。

2.锁升级

在 Java 并发编程中,锁升级(Lock Escalation) 是 JVM 对 synchronized 锁的优化机制,它会根据锁竞争情况动态调整锁状态,从低开销状态逐步升级到高开销状态。这是 Java 性能优化的关键特性(自 JDK 1.6 引入)。

🔄 锁升级的四个阶段

无锁
偏向锁
轻量级锁
重量级锁

1. 无锁状态(No Lock)

  • 特征:对象刚创建时,没有任何线程访问
  • 开销:无任何锁操作成本
  • 对象头标志001

2. 偏向锁(Biased Lock)

  • 适用场景单线程重复访问同步块
  • 优化原理
    • 在对象头记录首个获得锁的线程ID
    • 同一线程后续进入同步块时无需 CAS 操作
  • 对象头标志101
  • 升级触发:当其他线程尝试获取锁时

3. 轻量级锁(Lightweight Lock)

  • 适用场景多线程交替执行(无实际竞争)
  • 实现机制
    1. 在栈帧创建锁记录(Lock Record)
    2. 通过 CAS 将对象头替换为指向锁记录的指针
    3. 成功:获得锁;失败:自旋尝试
  • 对象头标志00
  • 升级触发:自旋超过阈值(默认10次)或自旋时出现第三个线程竞争

4. 重量级锁(Heavyweight Lock)

  • 适用场景高并发竞争
  • 实现机制
    • 通过操作系统 mutex 互斥量实现
    • 未获锁线程进入阻塞队列(涉及内核态切换)
  • 对象头标志10
  • 特点:开销最大,但保证公平性

🧪 锁升级过程示例

public class LockEscalationDemo {private static final Object lock = new Object();private static int counter = 0;public static void main(String[] args) {// 阶段1: 偏向锁 (单线程)synchronized (lock) {counter++;}// 阶段2: 轻量级锁 (多线程交替)new Thread(() -> {for (int i = 0; i < 5; i++) {synchronized (lock) { counter++; }}}).start();// 阶段3: 重量级锁 (高并发竞争)for (int i = 0; i < 10; i++) {new Thread(() -> {synchronized (lock) { counter++; }}).start();}}
}

📊 锁状态对比表

特性偏向锁轻量级锁重量级锁
适用场景单线程访问多线程交替执行高并发竞争
实现方式记录线程IDCAS自旋操作系统mutex
开销极低中等
竞争处理升级为轻量级锁自旋失败则升级线程阻塞
对象头存储线程ID+epoch指向栈中锁记录指针指向监视器对象指针
是否阻塞自旋(非阻塞)是(内核阻塞)
公平性可配置

⚙️ 锁升级关键技术细节

  1. Mark Word 结构变化

    // 32位JVM对象头示例
    | 锁状态   | 25bit          | 4bit     | 1bit(偏向) | 2bit(锁标志) |
    |----------|----------------|----------|------------|--------------|
    | 无锁     | 哈希码         | 分代年龄 | 0          | 01           |
    | 偏向锁   | 线程ID+epoch   | 分代年龄 | 1          | 01           |
    | 轻量级锁 | 指向锁记录指针 |          |            | 00           |
    | 重量级锁 | 指向监视器指针 |          |            | 10           |
    
  2. 批量重偏向(Bulk Rebias)

    • 当一类对象的偏向锁被撤销超过阈值(默认20次),JVM 会认为该类不适合偏向锁
    • 后续该类的对象会直接进入轻量级锁状态
  3. 锁消除(Lock Elision)

    • JIT 编译器对不可能存在共享竞争的锁进行消除

      // 示例:局部StringBuffer的同步会被消除
      public String localMethod() {StringBuffer sb = new StringBuffer(); // 局部变量sb.append("Hello");return sb.toString();
      }
      

⚠️ 重要注意事项

  1. 锁降级不存在

    • 锁升级是单向过程(偏向→轻量→重量)
    • 一旦升级为重量级锁,不会降级(即使竞争消失)
  2. 偏向锁延迟启动

    • JVM 启动后前 4 秒默认禁用偏向锁(避免初始化时的无效偏向)

      # 关闭偏向锁(JDK 15+默认)
      -XX:-UseBiasedLocking
      
  3. 自旋优化

    • 轻量级锁的自旋次数由 JVM 自适应调整(Adaptive Spinning)
    • 基于前一次锁获取的成功率动态变化

💡 最佳实践建议

  1. 低竞争场景

    • 保持默认设置(允许锁升级)
    • 避免不必要的同步块
  2. 高竞争场景

    • 考虑使用 ReentrantLock 替代 synchronized
    • 利用 java.util.concurrent 高级并发工具
  3. 性能调优

    # 查看锁竞争情况
    -XX:+PrintSynchronizationStatistics# 禁用偏向锁(若确认高竞争)
    -XX:-UseBiasedLocking
    

锁升级的本质:JVM 在线程安全执行效率之间寻找最佳平衡点,开发者应理解其原理但避免过度干预自动优化。

3.ABA问题

ABA 问题详解

在并发编程中,ABA 问题是使用 CAS(Compare-And-Swap)操作时可能遇到的一种经典问题。它发生在共享变量的值经历了 A→B→A 的变化序列后,CAS 操作无法检测到中间状态变化的情况。

🔍 ABA 问题发生机制

线程1 共享变量 线程2 读取值 A 修改值 A→B 修改值 B→A 执行CAS(A→C):成功! 线程1 共享变量 线程2

问题本质

  • CAS 只检查值是否匹配,不关心值是否被修改过
  • 虽然最终值回到了 A,但中间状态变化被忽略
  • 可能导致数据一致性问题

⚠️ 经典案例:无锁栈实现中的 ABA

public class Stack {private AtomicReference<Node> top = new AtomicReference<>();public void push(Node node) {Node oldTop;do {oldTop = top.get();node.next = oldTop;} while (!top.compareAndSet(oldTop, node));}public Node pop() {Node oldTop;Node newTop;do {oldTop = top.get();if (oldTop == null) return null;newTop = oldTop.next;} while (!top.compareAndSet(oldTop, newTop));return oldTop;}
}

ABA 问题发生场景:

  1. 线程1读取栈顶节点 A
  2. 线程1被挂起
  3. 线程2弹出 A,栈顶变为 B
  4. 线程2弹出 B
  5. 线程2压入 A(新节点,地址相同)
  6. 线程1恢复执行,CAS 成功将 A 替换为 C
  7. 结果:C.next 指向 B,但 B 已被弹出,造成内存错误

🛡️ ABA 问题解决方案

1. 版本号机制(推荐)

为每个状态变化添加版本号戳记:

// Java 内置解决方案
AtomicStampedReference<V> // 带整数戳记的引用
AtomicMarkableReference<V> // 带布尔标记的引用

实现原理

匹配
不匹配
版本戳
CAS操作
同时检查值和版本号
更新值和版本号
操作失败

使用示例

public class ABASolution {private AtomicStampedReference<Integer> value = new AtomicStampedReference<>(0, 0); // 初始值=0, 版本=0public void update(int expectedValue, int newValue) {int[] stampHolder = new int[1];int oldStamp;int newStamp;do {// 读取当前值和版本int currentValue = value.get(stampHolder);oldStamp = stampHolder[0];// 验证值是否被修改过if (currentValue != expectedValue) {break; // 值已被其他线程修改}newStamp = oldStamp + 1; // 更新版本号} while (!value.compareAndSet(expectedValue, newValue, oldStamp, newStamp));}
}

2. 不重复使用内存地址

  • 确保被替换的对象不会被重用
  • 适用于对象池或资源管理场景
  • 实现复杂,不推荐作为通用方案

3. 延迟回收(GC 语言中)

  • 依赖垃圾回收机制防止对象复用
  • 在非 GC 环境(如 C/C++)中不可靠

📊 ABA 问题与其他并发问题对比

问题类型发生场景检测难度典型解决方案
ABA 问题CAS 操作版本号机制
竞态条件多线程无序访问同步锁
死锁多锁相互等待锁排序、超时机制
活锁线程持续重试失败随机退避策略

ABA 问题本质:CAS 操作只能检查值的相等性,无法检测值的历史变化。版本号机制通过添加状态元数据,将值检查扩展为状态机检查,从而解决这一问题。

http://www.dtcms.com/wzjs/92647.html

相关文章:

  • 苏宁易购网页布局设计济南seo官网优化
  • 电脑编程入门自学做关键词优化
  • 网页搜索一个网站全包百度官方客户端
  • 海南网站开发佛山seo整站优化
  • 手机网页及网站设计推广赚钱app哪个靠谱
  • 零基础学it从哪方面学起seo外包网络公司
  • 怎样利用网站做引流做市场推广应该掌握什么技巧
  • 美容行业培训网站建设世界大学排名
  • 百度做的网站后台怎么进网站seo什么意思
  • 宝马itms做课网站长沙seo排名收费
  • 常州网站制作策划怎么查权重查询
  • 重庆网站的建设千锋教育怎么样
  • 营销平台网站建设网络营销 长沙
  • 欧美免费1级做爰片在线观看网站淘宝直通车
  • wordpress全站pjax广安seo外包
  • 京东的网站是哪家公司做今日百度搜索风云榜
  • wordpress调用导航菜单aso优化吧
  • 兰州学校网站建设新闻稿范文300字
  • 论坛网站如何备案北京seo优化方案
  • 哪个网站做初中作业网络推广公司主要做什么
  • ui培训班 qfeduseo外包优化
  • 网站为什么会出现死链如何让产品吸引顾客
  • 做网站枣庄百度新闻下载安装
  • 分析网站关键词优化公司推荐
  • 广东省党的建设研究会网站目前常用的搜索引擎有哪些
  • 外星人做的网站进入百度搜索首页
  • wordpress删除 自豪的优化大师优化项目有哪些
  • 南京网站设计的公司北京网站建设公司案例
  • 做网站的无锡公众号软文怎么写
  • 如何做适合网站大小的图片关键词网站推广