0
0

More than 1 year has passed since last update.

【JavaGold】ReentrantLockクラス

Posted at

概要

synchronizedによる排他制御やatomicパッケージのクラスでは実現できない、複数のメソッドにまたがる排他制御を実現できる。

特徴

  • スレッドセーフであり、複数のスレッドから同時にアクセスされても、正しくロックを制御する。
  • 排他的なロック(獲得できるのは1つのスレッドだけ)を提供する。ロックを獲得したスレッドだけが保持し、他のスレッドはロックの解放を待つ必要がある。
  • 同じスレッドがロックを再帰的に獲得(スレッドがすでにロックを保持している場合、再度ロックを獲得)することができる。

主なメソッド

  • lock():ロックを獲得する。
    他のスレッドが既にロックを保持している場合は、呼び出し元のスレッドはロックの解放を待機する。同じスレッドが再帰的にロックを獲得することも可能。

  • unlock():ロックを解放する。
    ロックを保持していたスレッドが解放を行い、他のスレッドがロックを獲得できるようになる。
    対応するlock()の呼び出しとペアで使用する必要がある。

  • tryLock():ブロックせずにロックの獲得を試みる。

    • 他のスレッドが既にロックを保持している場合:falseを返す。
    • 獲得できた場合:trueを返す。
  • lockInterruptibly():割り込み可能な形式でロックを獲得する。
    他のスレッドが既にロックを保持している場合は、lockInterruptibly()の呼び出しはブロックされ、他のスレッドが割り込み要求を送信した場合にはInterruptedExceptionをスローする。

  • isHeldByCurrentThread():現在のスレッドがロックを保持しているかどうかを判定する。

    • ロックを保持している場合:trueを返す。
    • 保持していない場合:falseを返す。
  • getHoldCount():現在のスレッドがロックを獲得した回数を取得する。同じスレッドが再帰的にロックを獲得した場合、その回数が返される。

  • isLocked():ロックが獲得されているかどうかを判定する。

    • ロックが獲得されている場合:trueを返す。
    • 獲得されていない場合:falseを返す。
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockExample {
    private static ReentrantLock lock = new ReentrantLock();

    public static void main(String[] args) {
        new Thread(() -> {
            performTask("Thread 1");
        }).start();

        new Thread(() -> {
            performTask("Thread 2");
        }).start();
    }

    private static void performTask(String threadName) {
        lock.lock();
        try {
            System.out.println("Starting task from " + threadName);
            Thread.sleep(1000);
            System.out.println("Task completed from " + threadName);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

この例では、ReentrantLockを使用して2つのスレッドが同じロックを制御する。
各スレッドはperformTaskメソッドを呼び出し、ロックを獲得する。performTaskメソッド内で、スレッドはタスクを開始し、一定時間待機後、タスクを完了する。

実行すると、2つのスレッドが交互にタスクを実行するが、ロックメカニズムにより同時にタスクを実行することはない。
1つのスレッドがロックを保持している場合、もう一つのスレッドはロックの解放を待つ。

実行結果
Starting task from Thread 1
Task completed from Thread 1
Starting task from Thread 2
Task completed from Thread 2

上記の例では、ReentrantLockを使用してスレッド間の排他制御を実現している。
ロックの獲得と解放が正しく行われ、スレッド間でタスクの順序が保持されることが確認できる。

ロックと解除までの処理はtryブロックで囲み、解除はfinallyブロックで記述する。
これにより、いずれかのスレッドに何らかの例外が発生した場合でもロックは解除されるため、別のスレッドが処理を続けることができる。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0