javaの悲観的ロックの仕組みは?
Java では悲観的ロックを実装する方法は 2 つあります。
- synchronizedキーワード: synchronizedキーワードは、メソッドやコードブロックを修飾するために使用でき、あるスレッドがオブジェクトのロックを取得したとき、そのオブジェクトにアクセスしようとする他のスレッドは待機する必要があります。synchronizedキーワードは、コードブロックの原子性操作を保証し、複数のスレッドが共有データを同時に変更することによって引き起こされるコンカレンシーの問題を回避します。
ネイティブに日本語で言い換えると:
public class LockExample {
private int count = 0;
public synchronized void increment() {
count++;
}
}
- ReentrantLock クラス: ReentrantLock は Java が提供する、再入可能な排他制御 (同じロックを何回も取得できる) で、lock() メソッドでロックを取得し、unlock() メソッドでロックを解放することができます。ReentrantLock クラスは公平性の設定や待機中のスレッドの中断など、さらに柔軟かつ多彩な機能を提供しています。
サンプルコード:
import java.util.concurrent.locks.ReentrantLock;
public class LockExample {
private int count = 0;
private ReentrantLock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
}
どちらの方法も悲観的ロック実現方式で、いずれも同時並行の対立が起こることを前提として、共有リソースにアクセスする前にロックを取得し、他のスレッドのアクセスをブロックします。これとは逆に、楽観ロックは同時並行の対立が起こらないことを前提として操作を直接行い、コミット時に他のスレッドによるデータの変更の有無を検査します。