3分钟理解死锁、锁粗化、锁消除、synchronized

Java并发编程中的死锁、锁优化与synchronized深入解析
本文探讨了Java中的死锁现象,如何避免和处理,以及锁粗化、锁消除技术的原理。还介绍了synchronized关键字的使用和其在不同场景下的行为,包括对象锁与类锁的区别,以及逃逸分析在锁定策略中的应用。

1.死锁

     死锁是一种现象如线程A持有资源x,线程B持有资源y,线程A等待线程B释放资源y,线程B等待线程A释放资源x,两个线程都不释放自己持有的资源,则两个线程都获取不到对方的资源,就会造成死锁。
    Java中的死锁不能自行打破,所以线程死锁后,线程不能进行响应。所以一定要注意程序的并发场景,避免造成死锁。

2.锁粗化

    锁粗化是一种优化技术: 如果一系列的连续操作都对同一个对象反复加锁和解锁,甚至加锁操作都是出现在循环体体之中,就算真的没有线程竞争,频繁地进行互斥同步操作将会导致不必要的性能损耗,所以就采取了一种方案:把加锁的范围扩展(粗化)到整个操作序列的外部,这样加锁解锁的频率就会大大降低,从而减少了性能损耗。

3.锁消除

    锁消除是一种优化技术: 就是把锁干掉。当Java虚拟机运行时发现有些共享数据不会被线程竞争时就可以进行锁消除。
    那如何判断共享数据不会被线程竞争?
       利用逃逸分析技术:分析对象的作用域,如果对象在A方法中定义后,被作为参数传递到B方法中,则称为方法逃逸;如果被其他线程访问,则称为线程逃逸。在堆上的某个数据不会逃逸出去被其他线程访问到,就可以把它当作栈上数据对待,认为它是线程私有的,同步加锁就不需要了

4.synchronized

    synchronized是Java中的关键字:用来修饰方法、对象实例。属于独占锁、悲观锁、 可重入锁、非公平锁。
    1.作用于实例方法时,锁住的是对象的实例(this);
    2.当作用于静态方法时,锁住的是 Class类,相当于类的一个全局锁,会锁所有调用该方法的线程;
    3.synchronized 作用于一个非 NULL的对象实例时,锁住的是所有以该对象为锁的代码块。 它有多个队列,当多个线程一起访问某个对象监视器的时候,对象监视器会将这些线程存储在不同的容器中。 每个对象都有个 monitor 对象, 加锁就是在竞争 monitor 对象,代码块加锁是在代码块前后分别加上 monitorenter 和 monitorexit 指令来实现的,方法加锁是通过一个标记位来判断的。

### synchronized的工作原理 `synchronized`是Java中用于实现线程同步的关键字,它通过内置的监视器(Monitor)机制来控制多个线程对共享资源的访问。每个对象都有一个与之关联的监视器,当一个线程进入由`synchronized`修饰的代码块或方法时,它必须获取该对象的监视器,执行完毕后释放该。 在底层实现上,`synchronized`依赖于JVM的`monitorenter`和`monitorexit`指令[^5]。当线程执行到`monitorenter`指令时,会尝试获取对象的:如果未被占用,则成功获取;如果已被其他线程持有,则当前线程会被阻塞,直到被释放。执行完同步代码块后,JVM插入`monitorexit`指令以释放。 从Java SE 1.6开始,`synchronized`进行了多项优,包括偏向、轻量级、自旋等机制,使其性能显著提升。例如,在竞争不激烈的情况下,JVM会尝试使用自旋减少线程挂起带来的开销[^4]。此外,JVM还支持消除等优手段,进一步提升性能[^4]。 ### synchronized的使用方法 #### 1. 作用于实例方法 当`synchronized`修饰一个实例方法时,住的是调用该方法的对象实例。同一时间只有一个线程可以访问该对象的同步方法。 ```java public class SyncMethod { public synchronized void method() { // 同步代码 } } ``` #### 2. 作用于静态方法 当`synchronized`修饰静态方法时,住的是类的Class对象。这意味着所有该类的实例共享同一个。 ```java public class SyncStaticMethod { public static synchronized void staticMethod() { // 同步代码 } } ``` #### 3. 作用于代码块(推荐) 更灵活的方式是使用`synchronized`代码块,可以指定的对象。这种方式允许更细粒度的控制,避免不必要的同步开销。 ```java public class SyncBlock { private Object lock = new Object(); public void method() { synchronized (lock) { // 同步代码 } } } ``` #### 4. 作用于类对象 也可以直接对类加,适用于控制整个类级别的并发访问。 ```java public class ClassName { public void method() { synchronized (ClassName.class) { // 同步代码 } } } ``` ### 使用注意事项 - **避免死锁**:多个线程同时请求多个时,若顺序不当可能导致死锁。 - **尽量减小同步范围**:过多的同步操作会影响程序性能,应尽可能缩小同步代码的范围。 - **理解的作用域**:非静态方法的属于对象级别,而静态方法或类的属于类级别,两者互不影响。 ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值