JAVA学習メモ(マルチスレッド4) - スレッドセーフティ3(スレッド同期機構 - ロック)
方法3:Lock(ロック)(JDK5.0以降に追加)
スレッドセーフの問題を解決する方法(同期機構) ~同期を実現する第3の方法~ > Lock(ロック)
- JDK 5.0 以降、Java はより強力なスレッド同期メカニズムを提供します。同期は、同期ロック オブジェクトを明示的に定義することによって実現されます。同期ロックは、Lock オブジェクトを使用して実装されます。
- java.util.concurrent.locks.Lock インターフェースは、複数のスレッドによる共有リソースへのアクセスを制御するツールです。
ロックは、共有リソースへの排他的アクセスを提供します。一度に 1 つのスレッドのみが Lock オブジェクトをロックでき、スレッドは共有リソースへのアクセスを開始する前に Lock オブジェクトを取得する必要があります。 - ReentrantLock クラスは、synchronized と同じ同時実行性とメモリ セマンティクスを備えた Lock を実装します。スレッド セーフな制御を実装する場合は、明示的にロックとロックを解放できる ReentrantLock がより一般的に使用されます。
面接でよくある質問: 同期とロックの類似点と相違点は何ですか?
同じ:
どちらもスレッド セーフティの問題を解決できます
違う:
- 同期メカニズムは、対応する同期コードの実行後に同期モニターを自動的に解放します。
- ロックは同期を手動で開始する必要があり (lock() メソッド)、同期の終了も手動で実装する必要があります (unLock() メソッド)。
同期メソッドの推奨優先順位:
ロック → 同期コード ブロック (すでにメソッド本体に入り、対応するリソースが割り当てられている) → 同期メソッド (メソッド本体の外)
LockTest (Runnable インターフェイスの実装を使用して、スレッド同期メカニズム Lock (ロック) を実装します)
class Windows6 implements Runnable{
private int ticket=100;
//1.实例化ReentrantLock
private ReentrantLock lock=new ReentrantLock();
@Override
public void run() {
try{
//2.调用上锁方法lock()
lock.lock();
while (true){
if (ticket>0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "卖票,票号为:" + ticket);
ticket--;
}else {
break;
}
}
}finally {
//3.调用解锁方法unlock()
lock.unlock();
}
}
}
public class LockTest {
public static void main(String[] args) {
Windows6 windows = new Windows6();
Thread t1 = new Thread(windows);
Thread t2 = new Thread(windows);
Thread t3 = new Thread(windows);
t1.setName("窗口1");
t2.setName("窗口2");
t3.setName("窗口3");
t1.start();
t2.start();
t3.start();
}
}
LockTest1 (Threadクラスを継承するメソッドを利用してスレッド同期機構Lock(ロック)を実装)
class Windows7 extends Thread{
private static int ticket=100;
//1.实例化ReentrantLock
private static ReentrantLock lock=new ReentrantLock();
@Override
public void run() {
try{
//2.调用上锁方法lock()
lock.lock();
while (true){
if (ticket>0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "卖票,票号为:" + ticket);
ticket--;
}else {
break;
}
}
}finally {
//3.调用解锁方法unlock()
lock.unlock();
}
}
}
public class LockTest1 {
public static void main(String[] args) {
Windows7 windows1=new Windows7();
Windows7 windows2=new Windows7();
Windows7 windows3=new Windows7();
windows1.setName("窗口1");
windows2.setName("窗口2");
windows3.setName("窗口3");
windows1.start();
windows2.start();
windows3.start();
}
}