同期ロックの対象
Javaのすべてのオブジェクトは、ロックとして機能できます。これは、次の3つの形式で表されます。
- 通常の同期メソッドの場合、ロックは現在のインスタンスオブジェクトです。
- 静的同期メソッドの場合、ロックは現在のクラスバイトコードであるClassオブジェクトです。
- 同期されたメソッドブロックの場合、ロックは同期されたブラケットで構成されたオブジェクトです
公正および不公正なロック
不当なロック
private final ReentrantLock lock = new ReentrantLock();
// private final ReentrantLock lock = new ReentrantLock(false);
他のスレッドを飢えさせる可能性のある不公平なロック。(一人ですべての作業を行います。誰かがいるかどうかを尋ねるのではなく、つかむだけです)
高効率
フェアロック
private final ReentrantLock lock = new ReentrantLock(true);
太陽が輝いているので、誰かいるのか聞いてみると、行列ができます。
効率は比較的低いです。
リエントラントロック/再帰ロック
リエントラントロック機能のデモンストレーション:外側のロックを開いた後、内側のロックを開き続けることができます
public static void main(String[] args) {
Object o = new Object();
new Thread(()->{
synchronized (o) {
System.out.println(Thread.currentThread().getName() + "外层");
synchronized (o) {
System.out.println(Thread.currentThread().getName() + "内层");
}
}
},"AA").start();
}
再入可能ロックは、再帰呼び出しを繰り返すことができます
public class SyncLockDemo {
public synchronized void add(){
add();
}
public static void main(String[] args) {
new SyncLockDemo().add();
}
}
デッドロック
デッドロックとは:
リソースの競合により、2つ以上のプロセスが互いに待機します。外部干渉がない場合、プロセスは実行できなくなります。
デッドロックの原因
- 不十分なシステムリソース
- プロセス実行の事前注文は不適切です
- リソースの誤配分
デッドロックの例
public class DeadLock {
//创建两个对象
static Object a = new Object();
static Object b = new Object();
public static void main(String[] args) {
new Thread(()->{
synchronized (a) {
System.out.println(Thread.currentThread().getName() + "持有锁a, 试图获取锁b");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (b) {
System.out.println(Thread.currentThread().getName() + "获取到锁b");
}
}
},"AA").start();
new Thread(()->{
synchronized (b) {
System.out.println(Thread.currentThread().getName() + "持有锁b, 试图获取锁a");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (a) {
System.out.println(Thread.currentThread().getName() + "获取到锁a");
}
}
},"BB").start();
}
}
デッドロックを確認します
- jps -lは、実行中のプログラムのプロセス番号を取得します
- jstackプロセス番号は、デッドロックが発生したかどうかを確認できます