マルチスレッドでは、スレッドセーフを確保するために、コードの同期とロックに同期とロックを使用することがよくありますが、両者の具体的な違いと、シナリオが明確でない場合の使用に適したものは何ですか。違いはおおまかに次のとおりです。
違い
1. SynchronizedはJavaキーワードであり、LockはJavaのインターフェースです。
2. Synchronizedは自動的にロックを解除し、Lockは手動でロックを解除する必要があります
3.同期は中断できません。ロックは中断することも中断しないこともできます
4. Lockを使用すると、スレッドがロックを取得したかどうかを知ることができますが、同期はできません
5. Synchronizedはメソッドとコードブロックをロックできますが、Lockはコードブロックのみをロックできます
6. Lockは、読み取りロックを使用して、マルチスレッド読み取りの効率を向上させることができます
7. Synchronizedは非フェアロックであり、ReentranLockはそれがフェアロックであるかどうかを制御できます
Lockインターフェースから、主に5つのメソッドがあることがわかります。これらのメソッドの機能は、コメントからわかります。
- lock():ロックを取得します。ロックが一時的に使用されている場合は、永久に待機します
- ロック解除():ロックを解除します
- tryLock():戻り値の型はブール値であることに注意してください。ロックの取得時にロックが占有されている場合はfalseを返し、そうでない場合はtrueを返します。
- tryLock(long time、TimeUnit unit):tryLock()と比較して、パラメーターの待機時間を確保するための時間制限があります
- lockInterruptibly():ロックを取得する方法。スレッドがロックを取得してステージに入るのを待っている場合は、このスレッドを中断
して、上記の説明で他のことを行うことができます。これ は、前のセクションで一般的に説明できます。ロックタイプ(lockInterruptibly())」、「ロック状態(tryLock())」などの問題、および前のサブセクションでの取得プロセス「ロックの取得を試みることができるのはおおまかに言って、スレッド永遠に待つことはできません」はい、その理由。
ロック():
public class LockTest {
private Lock lock = new ReentrantLock();
private void method(Thread thread) {
lock.lock();
try {
System.out.println(thread.getName() + " has gotten the lock!");
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println(thread.getName() + " has unlocked the lock!");
lock.unlock();
}
}
public static void main(String[] args) {
final LockTest test = new LockTest();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
test.method(Thread.currentThread());
}
}, "t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
test.method(Thread.currentThread());
}
}, "t2");
t1.start();
t2.start();
}
}
演算結果:
t1 has gotten the lock!
t1 has unlocked the lock!
t2 has gotten the lock!
t2 has unlocked the lock!
tryLock():
public class LockTest {
private Lock lock = new ReentrantLock();
private void method(Thread thread) {
if (lock.tryLock()) {
lock.lock();
try {
System.out.println(thread.getName() + " has gotten the lock!");
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println(thread.getName() + " has unlocked the lock!");
lock.unlock();
}
} else {
System.out.println("I'm "+thread.getName()+". Someone has gotten the lock!");
}
}
public static void main(String[] args) {
LockTest test = new LockTest();
Thread t1 = new Thread(() -> test.method(Thread.currentThread()), "t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
test.method(Thread.currentThread());
}
}, "t2");
t1.start();
t2.start();
}
}
演算結果:
t1 has gotten the lock!
t1 has unlocked the lock!
I'm t2. Someone has gotten the lock!
これを見て、誰もがLockの使い方を使うと思います。tryLock(長時間、TimeUnitユニット)とlockInterruptibly()については詳しく説明しません。前者は主に待ち時間があり、テストコードに待ち時間が記述されています。後者は主に割り込みを待機し、あまり使用されない割り込み例外をスローします。探索したい場合は、自分で調べることができます。