Java ReentrantLockクラス - 明示的にロックを取得
明示的にロックを取得 - ReentrantLockクラス
public void lock()
public void unlock()
synchronizedブロックによる同期は、アプリケーション開発者がロックの取得/解放を意識しなくてもよいため、「暗黙的なロック」と呼ばれます。逆に、メソッドを通じて「明示的にロック」をかけたり解除したりしたい場合があります。このような場合は、ReentrantLockクラス(java.util.concurrent.locksパッケージ)を利用します。
ReentrantLockクラスでは、lockメソッドで明示的にロックした後、unlockメソッドで解放する必要があります。
次は、synchronized修飾子を使用した例(incrementメソッド)をReentrantLockクラスで書き直したものです。
LockSample.java
package com.devkuma.basic.thread;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockSample {
private int count;
private final Lock lock = new ReentrantLock();
public static void main(String[] args) {
LockSample ls = new LockSample();
ls.execute();
}
public void execute() {
final int THREAD_MAX = 300000;
Thread[] ts = new Thread[THREAD_MAX];
for (int i = 0; i < THREAD_MAX; i++) {
ts[i] = new Thread(new MyThread(this));
ts[i].start();
}
for (int i = 0; i < THREAD_MAX; i++) {
try {
ts[i].join();
} catch (InterruptedException e) {
System.out.println(e);
}
}
System.out.println(count);
}
public void increment() {
lock.lock();
try {
this.count++;
} finally {
lock.unlock();
}
}
private static class MyThread implements Runnable {
private LockSample _counter;
public MyThread(LockSample counter) {
this._counter = counter;
}
@Override
public void run() {
_counter.increment();
}
}
}
実行結果:
300000
ReentrantLockクラスでlockメソッドを使用する場合は、その直後をtryブロックで囲む必要があります。これは、処理中に予期しない例外が発生した場合でも、finally節でunlockメソッドが呼び出されることを保証するためです。