Synchronized是非公平锁吗?那么如何体现?锁能降级吗?

1. synchronized 是非公平锁吗?

是的,synchronized 是非公平锁。

什么是非公平锁?

非公平锁意味着线程获取锁的顺序并不一定按照先后到达的顺序,也就是说,后来的线程有可能插队,优先获取锁。这种机制可以减少线程切换的开销,提高系统的吞吐量。

如何体现 synchronized 的非公平性?

sychronized 的非公平性体现在JVM 的内部实现上。当多个线程竞争锁时,synchronized 并不会按照线程请求锁的顺序来安排锁的获取,而是让竞争最激烈的线程尽快获取锁。这种设计有助于避免某些线程长期得不到锁的情况,也能加快线程获取锁的速度。

2. 锁能降级吗?

synchronized 机制下,锁不能降级。

什么是锁降级?

锁降级是指将持有的高等级锁(如写锁)降级为低等级锁(如读锁)的过程。常见于可重入锁(如 ReentrantReadWriteLock)中,降级可以通过以下过程实现:

  1. 持有写锁时,如果希望多个线程进行只读访问,先获取读锁再释放写锁。
  2. 降级允许系统在保持一定并发性能的同时,提供必要的线程安全性。

但在 synchronized 机制中,锁的持有要么是独占锁(写锁),要么没有持有,不支持类似读写锁的降级行为。

3. synchronized 的实现机制

synchronized 是 JVM 内置的锁机制,基于对象头MarkWord 字段,通过偏向锁、轻量级锁和重量级锁来实现对锁的优化。

  • 偏向锁:当只有一个线程竞争时,线程偏向锁住对象,几乎无性能损耗。
  • 轻量级锁:当多个线程开始竞争时,会升级为轻量级锁,通过自旋等待的方式减少上下文切换。
  • 重量级锁:当自旋等待的时间过长或线程数量增多时,锁升级为重量级锁,涉及线程阻塞和唤醒机制,性能相对较差。

synchronized 中,锁升级是可以的(从偏向锁到重量级锁),但锁降级是不可用的。

4. 锁的非公平性和实现的设计考量

非公平锁在高并发情况下可以提升系统的吞吐量。synchronized 采用非公平锁的原因是:

  1. 避免线程饥饿:如果采用公平锁,会导致后续线程等待锁的时间较长,增加了线程切换的成本。
  2. 提高吞吐量:非公平锁允许后来的线程有机会获取锁,减少了线程排队等待的时间,提高了锁的获取速度和系统的整体效率。

5. 如何检测 synchronized 的非公平性

可以通过设计一个多线程竞争锁的场景来观察:

public class SynchronizedFairnessTest {
    
    
    private static int counter = 0;

    public synchronized static void increment() {
    
    
        counter++;
        System.out.println(Thread.currentThread().getName() + " incremented counter to: " + counter);
    }

    public static void main(String[] args) {
    
    
        Runnable task = () -> {
    
    
            for (int i = 0; i < 5; i++) {
    
    
                increment();
                try {
    
    
                    Thread.sleep(50); // 模拟其他操作
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        };

        // 创建多个线程,模拟并发
        Thread t1 = new Thread(task, "Thread 1");
        Thread t2 = new Thread(task, "Thread 2");
        Thread t3 = new Thread(task, "Thread 3");

        t1.start();
        t2.start();
        t3.start();
    }
}

在多线程的环境下,Thread 1Thread 2Thread 3 的执行顺序是非确定性的,因为 synchronized 不保证公平性。

6. 业务场景和问题解决

在高并发业务场景下,比如订单处理系统中多个线程同时处理订单生成操作时,synchronized 非公平锁可以提高吞吐量,让高并发的请求迅速得到处理。但在某些对顺序要求严格的场景下(如日志系统、数据审计),这种非公平性可能会带来问题。因此,在需要严格控制线程获取锁顺序的场景中,可以考虑使用 ReentrantLock 并设置其为公平锁。

猜你喜欢

转载自blog.csdn.net/qq_41520636/article/details/143135485