スレッドの同期とデッドロック
プログラム開発では、すべてのプログラムはmainメソッドによって実行され、mainメソッド自体はメインスレッドに属しているため、mainメソッドによって作成される新しいスレッドオブジェクトは子スレッドです。
サブスレッドを利用することで、非同期の演算処理を行うことができるため、メインスレッドの動作に影響を与えることなく、他の演算を行うことができ、プログラムの実行速度が速くなるだけでなく、遅延が大きくなりません。
同期運転
いわゆる同期操作とは、コード内の複数の操作が同じ時間内に1つのスレッドでのみ実行でき、他のスレッドがこのスレッドの完了を待ってから実行を続行できることを意味します。
:Javaでキーワードを同期同期スレッドを使用することができ、キーワードが2つの方法で使用することができる
1同期コードブロック:パッケージを使用してコードブロックの同期が、同期オブジェクトを指定する必要性は、一般的に、これに設定されている。
2 。同期方法:同期によって定義された方法を使用します。
例:同期されたコードブロックを観察する
package Project.Study.Multithreading;
class MyThread7 implements Runnable{
private int ticket=10; //一共有10张票
@Override
public void run(){
for (int x=0;x<10;x++){
synchronized(this){ //定义同步代码块
if(this.ticket>0){ //判断当前是否还有剩余票
try {
Thread.sleep(100); //休眠1s,模拟延迟
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+",卖票,ticket="+this.ticket--);
}
}
}
}
}
public class Test7 {
public static void main(String [] args){
MyThread7 mt=new MyThread7();
new Thread(mt,"票贩子A").start(); //启动多线程
new Thread(mt,"票贩子B").start();
new Thread(mt,"票贩子C").start();
new Thread(mt,"票贩子D").start();
}
}
//结果:
//票贩子A,卖票,ticket=10
//票贩子A,卖票,ticket=9
//票贩子A,卖票,ticket=8
//票贩子A,卖票,ticket=7
//票贩子A,卖票,ticket=6
//票贩子A,卖票,ticket=5
//票贩子A,卖票,ticket=4
//票贩子A,卖票,ticket=3
//票贩子A,卖票,ticket=2
//票贩子A,卖票,ticket=1
例:同期方法を使用して問題を解決する
package Project.Study.Multithreading;
class MyThread8 implements Runnable{
private int ticket=10; //一共有10张票
@Override
public void run(){
for (int x=0;x<20;x++){
this.sale(); //卖票操作
}
}
public synchronized void sale(){//同步方法
if (this.ticket>0){ //判断当前是否还有剩余票
try{
Thread.sleep(100);//休眠1s,模拟延迟
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+",卖票,ticket="+this.ticket--);
}
}
}
public class Test8 {
public static void main(String []args){
MyThread8 mt=new MyThread8();
new Thread(mt,"票贩子A").start();//启动多线程
new Thread(mt,"票贩子B").start();
new Thread(mt,"票贩子C").start();
new Thread(mt,"票贩子D").start();
}
}
//结果:
//票贩子A,卖票,ticket=10
//票贩子A,卖票,ticket=9
//票贩子A,卖票,ticket=8
//票贩子A,卖票,ticket=7
//票贩子A,卖票,ticket=6
//票贩子A,卖票,ticket=5
//票贩子A,卖票,ticket=4
//票贩子A,卖票,ticket=3
//票贩子A,卖票,ticket=2
//票贩子A,卖票,ticket=1
注:
1. static、native、およびsynchronizedのメソッドは、同時に "abstract"で宣言することはできません。
2.スレッドがオブジェクトの同期メソッドに入ると、他のスレッドはこのオブジェクトの他のメソッドにアクセスできません。
3.同期コードのパフォーマンスは低下しますが、データセキュリティは高くなります(スレッドセキュリティは高くなります)。非同期コードの方が効率的ですが、スレッドセキュリティは低くなります(ほとんどのデータは共有データです。つまり、他のスレッドで使用されます)。
デッドロック
同時操作が多すぎると、デッドロックの問題が発生し、プログラムが停止状態になる可能性があります。いわゆるデッドロックとは、2つのスレッドが最初に相互に完了するのを待っているため、プログラムが停滞することを意味します。通常、プログラムのデッドロックは、プログラムの実行中に発生します。
例:プログラムのデッドロック操作
package Project.Study.Multithreading;
class A{
public synchronized void say(B b){
System.out.println("A先生说:把你的笔记本给我,我给你笔,否则不给!");
b.get();
}
public synchronized void get(){
System.out.println("A先生:得到了笔记本,付出了笔,还是什么都干不了!");
}
}
class B{
public synchronized void say(A a){
System.out.println("B先生说:把你的笔给我,我给你笔记本,否则不给!");
a.get();
}
public synchronized void get(){
System.out.println("B先生:得到了笔,付出了笔记本,还是什么都干不了");
}
}
public class Test9 implements Runnable{
private static A a=new A(); //定义类对象
private static B b=new B();
public static void main(String[]args){
new Test9(); //实例化本类对象
}
public Test9(){ //构造方法
new Thread(this).start(); //启动线程
b.say(a); //互相引用
}
@Override
public void run(){
a.say(b); //互相引用
}
}
//结果:
//B先生说:把你的笔给我,我给你笔记本,否则不给!
//A先生说:把你的笔记本给我,我给你笔,否则不给!
//(程序将不会再向下执行,并且不会退出,此为死锁情况出现)
上記のプログラムでは、両方のクラスが同期メソッド定義を使用しているため、aオブジェクトはbオブジェクトの実行が完了するのを待機し、bオブジェクトはaオブジェクトの実行が完了するのを待機します。これにより、デッドロックが発生します。