スレッドの不安定性とスレッドのデッドロック、同期ロック同期
スレッドの不安定性とは何ですか?
複数のスレッドが同じリソースを共有する場合、実行する読み出しおよび書き込み動作を上に共有リソースの同期ロックを使用せずにすることであろう異常なプログラムの実行結果をもたらし、異常な結果データを生成します。例:2人がチケットを取得します。最後のチケットが強い場合、両方の人がチケットを目に見るので、両方が同時にチケットを取得します。その結果、両方の人がチケットを取得し、チケット数は1枚になります。
スレッドの不安定さの解決策は?
スレッドの不安定さの解決策は、スレッドをロックし、スレッド同期メカニズムを使用して同期することです。スレッドの同期は実際には待機メカニズムです。複数のスレッドが同じリソースにアクセスする場合、キューを形成するために待機プールに入り、前のスレッドが使い果たされ、次のスレッドがそれを使用するのを待つ必要があります。キューイング使用メカニズム。
同期ロックを同期する
形成メカニズム:キュー+ロック。
スレッドがオブジェクトの排他ロックを取得すると、他のスレッドは、スレッドがオブジェクトの使用を終了する(ロックを開く)のを待ってから使用する必要があります。
同期ロックを使用すると問題が発生しやすくなりますか?
- スレッドは、使用する前に前のスレッドの終了を待つ必要があります。これにより、プログラムの効率に問題が発生します。
- 複数のスレッドと複数のリソースオブジェクトロックの場合、スレッドは別のプロセスによって使用されるリソースを占有する可能性があり、スレッドがロックを解放するのを待機している状態になります。スレッドがロックを占有している場合は、その後、スレッドのデッドロックの問題が発生します。
- 優先度の高いスレッドが優先度の低いスレッドがロックを解放するのを待つ場合、パフォーマンスの問題に影響します(たとえば、多くの単純なスレッドは複雑なスレッドがトランザクションを処理するのを待っているため、実行効率に影響します)。
同期ロックの同期:同期メソッドと同期コードブロック同期メソッドの
デフォルトのロックはthis(現在のオブジェクト)であり、任意のオブジェクトがロックになる可能性があります。
private synchronized void buyTicket() {
System.out.println(Thread.currentThread().getName() + ":我抢到了一个票" + ticketnum--);
// 控制线程结束
if (ticketnum <= 0) {
falg = false;
}
}
同期コードブロック:通常、ロックとして操作する必要がある共有リソースまたはリソースオブジェクトを使用します。
private void buyTicket() {
synchronized (this){ // Obj 代表任何资源对象
System.out.println(Thread.currentThread().getName() + ":我抢到了一个票" + ticketnum--);
// 控制线程结束
if (ticketnum <= 0) {
falg = false;
}
}
}
PS:スレッドスリープ方式は、ロックを解除せずにスレッドを休ませて待機することです。待機とは、スレッドを待機領域に入れてロックを解除することです。
スレッドデッドロックとは何ですか?
スレッドのデッドロックは実際には上記で説明されています。複数のスレッドがいくつかの共通リソースを共有し、3つ以上のロックがある場合、それらはすべて互いにロックを解放するのを待機しているため、スレッドは待機状態になります。
例:私はペンを持っていますが、書くにはあなたの紙が必要で、書くには私のペンが必要です。しかし、私たちは皆、それが自分自身に手放されるのを待っており、結果として待っている状態になります。
成し遂げる:
// 笔对象
class Pen{}
// 纸对象
class Paper{}
// 写字
class Write implements Runnable{
static Pen pen = new Pen();
static Paper paper = new Paper();
int flag;
String name;
Write(int flag,String name){
this.flag = flag;
this.name = name;
}
@Override
public void run() {
try {
writeWork();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void writeWork() throws InterruptedException {
// 当flag 0时获取笔
if(flag==0){
synchronized (pen){
System.out.println(name+":拿到了笔");
Thread.sleep(2000);
// 然后去拿纸的锁
synchronized (paper){
System.out.println(name+":拿到了纸");
}
}
}else {
synchronized (paper){
System.out.println(name+":拿到了纸");
Thread.sleep(2000);
// 然后去拿纸的锁
synchronized (pen){
System.out.println(name+":拿到了笔");
}
}
}
}
}
/**
* Created by 一只会飞的猪 on 2021/3/8.
* 实现线程死锁现象,写字 = 笔 + 纸
*/
public class DeadLockThread {
public static void main(String[] args) {
new Thread(new Write(0,"小美")).start();
new Thread(new Write(1,"小丑")).start();
}
}
結果:シャオメイとピエロの両方が自分の錠を持って、人生を待ちました。
デッドロックを解決する方法は?
デッドロックを解決する良い方法はありません。通常、ビジネスニーズに応じて、オブジェクトのロックをロックおよびロック解除する準備ができています。上記の例を見てください。
1つのリソースを取得した後、2人でロックを解除し、別のリソースを取得するだけで済みます。
public void writeWork() throws InterruptedException {
// 当flag 0时获取笔
if(flag==0){
synchronized (pen){
System.out.println(name+":拿到了笔");
Thread.sleep(2000);
}
// 然后去拿纸的锁
synchronized (paper){
System.out.println(name+":拿到了纸");
}
}else {
synchronized (paper){
System.out.println(name+":拿到了纸");
Thread.sleep(2000);
}
// 然后去拿纸的锁
synchronized (pen){
System.out.println(name+":拿到了笔");
}
}
}
結果:両方とも幸せになることができます。
PS:同期ロックを同期します(暗黙的な同期)。スコープの実装後、ロックは自動的に解放されます。ロックロック(次のフィルム)はアクティブにロックを解除する必要があります(ディスプレイの同期)