Java并发编程--锁

根据分类标准我们把锁分为以下 7 大类别,分别是:

  1. 偏向锁/轻量级锁/重量级锁;
  2. 可重入锁/非可重入锁;
  3. 共享锁/独占锁;
  4. 公平锁/非公平锁;
  5. 悲观锁/乐观锁;
  6. 自旋锁/非自旋锁;
  7. 可中断锁/不可中断锁。

以上是常见的分类标准,下面我们来逐一介绍它们的含义。

偏向锁/轻量级锁/重量级锁

这三种锁特指 synchronized 锁的状态,通过在对象头中的 mark word 来表明锁的状态。

  • 偏向锁

如果自始至终,对于这把锁都不存在竞争,那么其实就没必要上锁,只需要打个标记就行了,这就是偏向锁的思想。一个对象被初始化后,还没有任何线程来获取它的锁时,那么它就是可偏向的,当有第一个线程来访问它并尝试获取锁的时候,它就将这个线程记录下来,以后如果尝试获取锁的线程正是偏向锁的拥有者,就可以直接获得锁,开销很小,性能最好。

  • 轻量级锁

JVM 开发者发现在很多情况下,synchronized 中的代码是被多个线程交替执行的,而不是同时执行的,也就是说并不存在实际的竞争,或者是只有短时间的锁竞争,用 CAS 就可以解决,这种情况下,用完全互斥的重量级锁是没必要的。轻量级锁是指当锁原来是偏向锁的时候,被另一个线程访问,说明存在竞争,那么偏向锁就会升级为轻量级锁,线程会通过自旋的形式尝试获取锁,而不会陷入阻塞。

  • 重量级锁

重量级锁是互斥锁,它是利用操作系统的同步机制实现的,所以开销相对比较大。当多个线程直接有实际竞争,且锁竞争时间长的时候,轻量级锁不能满足需求,锁就会膨胀为重量级锁。重量级锁会让其他申请却拿不到锁的线程进入阻塞状态。

 

可重入锁/非可重入锁

可重入锁指的是线程当前已经持有这把锁的状态下,能在不释放这把锁的情况下再次获取这把锁。

非可重入锁指的是虽然当前线程持有了这把锁,但是想再次获取这把锁也必须先释放锁后才能再次尝试获取。

/**
 * methodA 和methodB 都是同步方法,当线程进入 methodA 会获得该类的对象锁,
 * 在 methodA 对方法 methodB 做了调用,但是 methodB 也是同步的,因此该线程需要再次获得该对象锁。这期间其他线程无法获该对象锁。
 * 因此可重入性避免再次获取锁出现死锁的问题。
 */
public class LockTest {

    public synchronized void methodA() {
        System.out.println("methodA");
        methodB();
    }

    public synchronized void methodB() {
        System.out.println("methodB");
    }
}

 

共享锁/独占锁

共享锁指的是同一把锁可以被多个线程同时获得。

独占锁指的是这把锁只能同时被一个线程获得。

 

公平锁/非公平锁

公平锁的公平的含义在于如果线程现在拿不到这把锁,那么线程就都会进入等待,开始排队,在等待队列里等待时间长的线程会优先拿到这把锁,有先来先得的意思。而非公平锁就不那么“完美”了,它会在一定情况下,忽略掉已经在排队的线程,发生插队现象。

 

悲观锁/乐观锁

悲观锁的概念是在获取资源之前,必须先拿到锁,以便达到“独占”的状态,当前线程在操作资源的时候,其他线程由于不能拿到锁,所以其他线程不能来影响我。
乐观锁恰恰相反,它并不要求在获取资源前拿到锁,也不会锁住资源,乐观锁利用 CAS 理念,在不独占资源的情况下,完成了对资源的修改。
悲观锁适合用于并发写入多、临界区代码复杂、竞争激烈等场景,这种场景下悲观锁可以避免大量的无用的反复尝试等消耗。
乐观锁适用于大部分是读取,少部分是修改的场景,也适合虽然读写都很多,但是并发并不激烈的场景。在这些场景下,乐观锁不加锁的特点能让性能大幅提高。

 

自旋锁/非自旋锁

自旋锁的理念是如果线程拿不到锁,并不直接陷入阻塞或者释放CPU资源,而是开始利用循环不停的尝试获取锁。

非自旋锁如果拿不到锁,直接放弃。可能会陷入阻塞或排队。

 

可中断锁/不可中断锁

可中断锁在获取锁的过程中,可以在中断去做其他的事情,不需要一直等到获取到锁才离开。ReentrantLock 是一种典型的可中断锁,例如使用 ReentrantLock.lockInterruptibly() 方法在获取锁的过程中不想获取了,那么可以调用 Thread.interrupt() 方法终止线程。

不可中断锁一旦线程申请了锁,就只能等到拿到锁后才能进行其他的逻辑处理。synchronized 关键字修饰的锁代表不可中断锁。

 

posted @ 2020-07-12 20:57  景岳  阅读(105)  评论(0编辑  收藏  举报