Java同步机制的底层实现("Java 同步机制底层原理详解")

原创
ithorizon 6个月前 (10-21) 阅读数 16 #后端开发

Java 同步机制底层原理详解

一、Java同步机制的概述

Java同步机制是Java多线程编程中用于控制多个线程对共享资源访问的一种机制。在Java中,synchronized关键字和java.util.concurrent包中的各种同步工具类(如ReentrantLock、Semaphore等)都是同步机制的实现方法。本文将深入探讨Java同步机制的底层实现原理。

二、synchronized关键字

synchronized关键字是Java中实现同步的一种单纯方法。它可以修饰方法或代码块,确保同一时刻只有一个线程可以执行被synchronized修饰的代码。

2.1 同步方法的底层实现

同步方法在底层是通过JVM的锁机制来实现的。当一个线程尝试进入同步方法时,JVM会为该方法生成一个锁(Monitor),然后执行以下步骤:

  • 1. 检查锁是否已经被其他线程持有。
  • 2. 如果锁未被持有,则当前线程获得锁并执行同步方法。
  • 3. 如果锁已被其他线程持有,当前线程将被阻塞,等待锁释放。
  • 4. 当持有锁的线程执行完毕,释放锁,其他被阻塞的线程将有机会获得锁并执行。

2.2 同步代码块的底层实现

同步代码块也是通过JVM的锁机制实现的,但与同步方法不同的是,同步代码块可以指定锁对象。以下是同步代码块在底层实现的步骤:

  • 1. 线程进入同步代码块前,检查指定锁对象是否已被其他线程持有。
  • 2. 如果锁未被持有,当前线程获得锁并执行同步代码块。
  • 3. 如果锁已被其他线程持有,当前线程将被阻塞,等待锁释放。
  • 4. 当持有锁的线程执行完毕,释放锁,其他被阻塞的线程将有机会获得锁并执行。

三、Java对象头与锁

在Java中,对象头的Mark Word部分用于存储锁状态信息。Mark Word的结构如下:

32位系统:

+-------------------+-------------------+-------------------+-------------------+

| lock state | lock state | lock state | lock state |

+-------------------+-------------------+-------------------+-------------------+

| hash | hash | hash | hash |

+-------------------+-------------------+-------------------+-------------------+

| Java type | Java type | Java type | Java type |

+-------------------+-------------------+-------------------+-------------------+

| array length | array length | array length | array length |

+-------------------+-------------------+-------------------+-------------------+

64位系统:

+-------------------+-------------------+-------------------+-------------------+

| lock state | lock state | lock state | lock state |

+-------------------+-------------------+-------------------+-------------------+

| hash | hash | hash | hash |

+-------------------+-------------------+-------------------+-------------------+

| Java type | Java type | Java type | Java type |

+-------------------+-------------------+-------------------+-------------------+

| array length | array length | array length | array length |

+-------------------+-------------------+-------------------+-------------------+

Mark Word中存储的锁状态信息包括:轻量级锁、重量级锁、偏向锁、自旋锁等。下面分别介绍这些锁的底层实现。

3.1 轻量级锁

轻量级锁是JVM为了缩减锁的开销而引入的一种锁优化技术。当线程尝试获取一个未被其他线程持有的锁时,会使用CAS操作在Mark Word中设置锁状态,并将线程的指针指向当前线程。以下是轻量级锁的底层实现步骤:

1. 当线程尝试获取锁时,使用CAS操作将Mark Word中的锁状态设置为轻量级锁状态,并将线程的指针指向当前线程。

2. 如果CAS操作胜利,当前线程获得锁并执行同步代码。

3. 当持有锁的线程执行完毕,释放锁,将Mark Word中的锁状态恢复为无锁状态。

3.2 重量级锁

当轻量级锁竞争激烈时,JVM会升级为重量级锁。重量级锁的实现依存于操作系统提供的互斥量(Mutex)。以下是重量级锁的底层实现步骤:

1. 当线程尝试获取锁时,首先检查Mark Word中的锁状态。

2. 如果锁状态为无锁或轻量级锁,尝试使用CAS操作将锁状态升级为重量级锁。

3. 如果CAS操作胜利,当前线程将锁对象与操作系统互斥量相关性,并阻塞其他线程。

4. 当持有锁的线程执行完毕,释放锁,将Mark Word中的锁状态恢复为无锁状态,并唤醒其他被阻塞的线程。

3.3 偏向锁

偏向锁是JVM为了缩减无竞争场景下的锁开销而引入的一种锁优化技术。当线程第一次获取锁时,JVM会记录锁的持有者,后续只有该线程尝试获取锁时,才会胜利。以下是偏向锁的底层实现步骤:

1. 当线程尝试获取锁时,检查Mark Word中的锁状态。

2. 如果锁状态为无锁,使用CAS操作将锁状态设置为偏向锁状态,并记录当前线程为锁的持有者。

3. 如果当前线程是锁的持有者,直接获得锁并执行同步代码。

4. 当持有锁的线程执行完毕,释放锁,将Mark Word中的锁状态恢复为无锁状态。

3.4 自旋锁

自旋锁是JVM为了缩减线程在等待锁时的开销而引入的一种锁优化技术。当线程尝试获取锁时,会循环检查锁是否可用,而不是直接阻塞。以下是自旋锁的底层实现步骤:

1. 当线程尝试获取锁时,检查Mark Word中的锁状态。

2. 如果锁状态为无锁,使用CAS操作将锁状态设置为自旋锁状态。

3. 当前线程循环检查锁是否可用,如果锁可用,则获得锁并执行同步代码。

4. 当持有锁的线程执行完毕,释放锁,将Mark Word中的锁状态恢复为无锁状态。

四、Java并发工具类

除了synchronized关键字外,Java还提供了java.util.concurrent包,其中包含了一系列并发工具类,如ReentrantLock、Semaphore、CountDownLatch等。这些工具类在底层也是通过JVM的锁机制实现的,但提供了更多彩的功能。

4.1 ReentrantLock

ReentrantLock是Java中的一种可重入锁,它提供了与synchronized关键字类似的同步功能,但具有更高的灵活性。以下是ReentrantLock的底层实现步骤:

1. 当线程尝试获取锁时,ReentrantLock会使用CAS操作在锁对象中设置锁状态。

2. 如果CAS操作胜利,当前线程获得锁并执行同步代码。

3. 当持有锁的线程执行完毕,释放锁,将锁对象中的锁状态恢复为无锁状态。

4.2 Semaphore

Semaphore是一个计数信号量,它允许一定数量的线程同时访问共享资源。以下是Semaphore的底层实现步骤:

1. 当线程尝试获取信号量时,Semaphore会检查当前可用信号量的数量。

2. 如果信号量数量大于0,使用CAS操作缩减信号量数量,并允许当前线程访问共享资源。

3. 如果信号量数量为0,当前线程将被阻塞,等待其他线程释放信号量。

4. 当持有信号量的线程执行完毕,释放信号量,增多信号量数量,并唤醒其他被阻塞的线程。

4.3 CountDownLatch

CountDownLatch是一个倒计时计数器,它允许一个或多个线程等待其他线程完成操作。以下是CountDownLatch的底层实现步骤:

1. CountDownLatch初始化时,设置一个计数器的初始值。

2. 当线程执行完毕时,使用CAS操作缩减计数器的值。

3. 当计数器的值减为0时,唤醒所有等待的线程。

4. 等待的线程在CountDownLatch上调用await()方法,如果计数器的值不为0,则线程将被阻塞。

五、总结

Java同步机制是Java多线程编程中至关重要的一部分。本文详细介绍了synchronized关键字、Java对象头与锁、以及Java并发工具类的底层实现原理。懂得这些底层原理有助于我们更好地使用Java同步机制,尽大概缩减损耗多线程程序的性能和稳定性。


本文由IT视界版权所有,禁止未经同意的情况下转发

文章标签: 后端开发


热门