synchronized讲解

本文详细解析了Java中synchronized关键字的使用方式与作用原理,包括如何确保多线程环境下的一致性和安全性,以及不同对象实例间synchronized方法的执行特点。

一、当在一个类中同时存在多个synchronized修饰的代码块或函数时,要想安全,就必须让他们后面的对象一致,因为只有同一把锁才能安全(同步函数的锁this);

二、静态同步函数再进内存的时候不会创建对象,但是存在其所属类的字节码文件对象,属于class类型的对象,所以,静态同步函数的锁是其所属类的字节码文件对象

三、理解synchronized关键字

    1.synchronized 的作用域有两种

        1)是某个对象实例内,synchronized  aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法(如果一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其他线程不能同时访问这个对象中任何一个synchronized方法),这时,不同的对象实例的synchronized方法时不相干扰的,也就是说,其他线程照样可以同时访问相同类的另一个对象实例中的synchronized方法。

<think>我们被要求讲解Java中synchronized锁的工作原理和使用方法。根据用户提供的引用内容,我们可以从以下几个方面进行讲解: 1. synchronized的基本使用(包括修饰实例方法、静态方法、代码块) 2. synchronized的实现原理(对象头、Monitor、锁升级机制) 3. 锁的种类(乐观锁、悲观锁、自旋锁、可重入锁等)以及synchronized作为悲观锁、可重入锁的特性 4. 锁升级机制(无锁、偏向锁、轻量级锁、重量级锁) 我们将按照以下结构组织回答: 一、synchronized的基本使用 1.1 修饰实例方法 1.2 修饰静态方法 1.3 修饰代码块 二、synchronized的实现原理 2.1 对象头(Object Header) 2.2 Monitor(监视器锁) 2.3 锁升级机制(无锁 -> 偏向锁 -> 轻量级锁 -> 重量级锁) 三、synchronized的特性 3.1 可重入性 3.2 互斥性 四、使用示例 五、总结 同时,我们会在回答中引用用户提供的引用标记[^1][^2][^3][^4][^5]来支持我们的讲解。 注意:由于用户要求参考站内引用,并且这些引用是关于synchronized的,所以我们将尽可能使用这些引用来构建答案。 开始回答:</think>### Java中synchronized锁原理及使用详解 #### 一、synchronized基础原理 **实现核心**:基于对象头中的Mark Word和Monitor监视器锁实现线程同步[^3] ```mermaid graph LR A[线程进入同步块] --> B[检查对象锁状态] B -->|无锁| C[通过CAS获取偏向锁] B -->|有锁| D[检查持有线程] D -->|当前线程| E[重入计数+1] D -->|其他线程| F[升级为轻量级锁] F -->|竞争激烈| G[膨胀为重量级锁] ``` **对象头结构**(64位JVM): ``` | 锁状态 | 25bit | 31bit | 1bit(偏向锁) | 4bit(锁标志) | |----------|----------------|-------------------|-------------|-------------| | 无锁 | unused | identity_hashcode | 0 | 01 | | 偏向锁 | threadID(54bit)| epoch(2bit) | 1 | 01 | | 轻量级锁 | 指向栈中锁记录指针 | 00 | | 重量级锁 | 指向Monitor指针 | 10 | ``` *锁标志位决定锁状态[^3]* #### 二、锁升级机制(JDK 6+优化) 1. **无锁状态** 新创建对象默认状态,无线程竞争 2. **偏向锁** - 场景:单线程重复访问 - 原理:在Mark Word记录线程ID - 优势:消除无竞争时的同步开销 - 触发:首次通过CAS设置线程ID[^2] 3. **轻量级锁** - 场景:多线程交替执行(无并发竞争) - 原理:拷贝对象头到线程栈,通过CAS竞争锁记录指针 - 失败触发自旋锁(默认10次) 4. **重量级锁** - 场景:高并发竞争 - 原理:通过操作系统互斥量(Mutex)实现 - 关联Monitor对象: ```java ObjectMonitor { _header; // 对象头 _count; // 重入次数 _waiters; // 等待线程数 _recursions; // 锁重入次数 _owner; // 持有线程 _EntryList; // 阻塞队列 _WaitSet; // 等待队列 } ``` 线程竞争时进入_EntryList阻塞[^5] #### 三、使用方式详解 1. **实例方法锁**(锁当前对象) ```java public synchronized void increment() { count++; // 锁对象是this } ``` *不同实例互不影响[^4]* 2. **静态方法锁**(锁类对象) ```java public static synchronized void staticMethod() { // 锁对象是Class对象(如MyClass.class) } ``` 3. **代码块锁**(指定锁对象) ```java public void method() { synchronized(lockObj) { // 显式指定锁对象 // 临界区代码 } } ``` #### 四、关键特性 1. **可重入性** 同一线程可重复获取锁(通过_recursions计数器实现) ```java synchronized void a() { b(); } synchronized void b() { } // 允许重入 ``` 2. **内存语义** - 进入同步块:刷新工作内存 → 主内存 - 退出同步块:写回工作内存 → 主内存 - 保证可见性和有序性(类似volatile) 3. **锁优化策略** | 策略 | 触发条件 | 实现方式 | |------------|--------------------------|-----------------------| | 锁消除 | 逃逸分析确定无竞争 | JIT编译时移除同步操作 | | 锁粗化 | 连续操作同一锁对象 | 合并多个同步块 | | 自适应自旋 | 根据历史成功率动态调整 | 减少线程切换开销 | #### 五、使用示例 ```java public class Counter { private int count = 0; private final Object lock = new Object(); // 专用锁对象 // 实例方法锁 public synchronized void add() { count++; } // 静态方法锁 public static synchronized void log() { System.out.println("Static lock"); } // 代码块锁(更细粒度控制) public void reset() { synchronized(lock) { // 使用专用锁对象 count = 0; System.out.println("Reset counter"); } } } ``` #### 六、性能注意事项 1. **优先使用代码块锁**:缩小同步范围 2. **避免锁静态方法**:可能导致类级并发瓶颈 3. **锁分离技术**:读写锁分离(如ReentrantReadWriteLock) 4. **监控锁竞争**:通过JConsole或VisualVM观察: - 锁等待时间 - 持有锁线程数 - 阻塞线程数 > 💡 **最佳实践**:在低竞争场景用`synchronized`(JVM优化完善),高竞争场景考虑`ReentrantLock`(支持公平锁/条件变量)[^5]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值