JAva Synchronizedキーワードとデッドロック
4655 ワード
Synchronizedキーワード
簡単なコードを使ってスレッドの“デッドロック”を実現して、この問題はSynchronizedキーワードを試験します
Java言語のキーワードは、メソッドまたはコードブロックを修飾するために使用される場合、同じ時点で最大1つのスレッドだけがセグメントコードを実行することを保証します.
2つの同時スレッドが同じオブジェクトobjectのsynchronized(this)同期コードブロックにアクセスすると、1時間に1つのスレッドしか実行できません.別のスレッドは、現在のスレッドがこのコードブロックを実行するまで待たなければなりません.
しかしながら、あるスレッドがobjectのsynchronized(this)同期コードブロックにアクセスすると、別のスレッドはobject内の非synchronized(this)同期コードブロックにアクセスすることができる.
特に重要なのは、1つのスレッドがobjectのsynchronized(this)同期コードブロックにアクセスすると、他のスレッドがobject内の他のすべてのsynchronized(this)同期コードブロックへのアクセスがブロックされることです.
スレッドがobjectのsynchronized(this)同期コードブロックにアクセスすると、このobjectのオブジェクトロックが得られる.その結果、objectオブジェクトのすべての同期コード部分への他のスレッドのアクセスが一時的にブロックされる.
このプログラムが実行されると、x 1はx 2を待っているため、x 2はx 1を待っているため、硬直状態になり、デッドロックが発生する.
この時、少し修正して、私はThreadクラスのsleep方法を使わないで、Objectクラスのwait方法を変えて、この時デッドロックが発生しないで、これもwaitとsleepの違いを検証しました:
waitメソッドは現在のオブジェクトのロックを解放しますが、sleepメソッドは現在のオブジェクトのロックを解放しません.
スレッドt 1とt 2は、どちらのスレッドが先に実行されるとは限らないので、3,4行目の位置が入れ替わる場合があるかもしれないが、flag=0の場合、x 1オブジェクトwaitの時間は1000 msであり、このときx 1のオブジェクトロックが解放され、終了を待つ(つまり1000 ms以内)、flag=1の条件がx 2およびx 1オブジェクトを実行済みとなり、このときflag=0はx 1オブジェクトを実行し続け、つまり、常に1リリース、0リリースです.
ただしwait()メソッドとnotify()メソッドは同期コードブロックにしか入れられません.同期コードブロックで使用しない場合、コンパイル時にエラーは発生しませんが、実行時にjava.lang.I llegalMonitorStateException異常が放出されます.
簡単なコードを使ってスレッドの“デッドロック”を実現して、この問題はSynchronizedキーワードを試験します
Java言語のキーワードは、メソッドまたはコードブロックを修飾するために使用される場合、同じ時点で最大1つのスレッドだけがセグメントコードを実行することを保証します.
2つの同時スレッドが同じオブジェクトobjectのsynchronized(this)同期コードブロックにアクセスすると、1時間に1つのスレッドしか実行できません.別のスレッドは、現在のスレッドがこのコードブロックを実行するまで待たなければなりません.
しかしながら、あるスレッドがobjectのsynchronized(this)同期コードブロックにアクセスすると、別のスレッドはobject内の非synchronized(this)同期コードブロックにアクセスすることができる.
特に重要なのは、1つのスレッドがobjectのsynchronized(this)同期コードブロックにアクセスすると、他のスレッドがobject内の他のすべてのsynchronized(this)同期コードブロックへのアクセスがブロックされることです.
スレッドがobjectのsynchronized(this)同期コードブロックにアクセスすると、このobjectのオブジェクトロックが得られる.その結果、objectオブジェクトのすべての同期コード部分への他のスレッドのアクセスが一時的にブロックされる.
package multithread_learning;
/**
* @author xiaohao
* @date :Aug 7, 2017 3:11:26 PM
* @version 1.0
*/
public class TestSynchronized {
public static void main(String[] args) {
// TODO Auto-generated method stub
Sy sy = new Sy(0);
Sy sy2 = new Sy(1);
sy.setName("t1");
sy2.setName("t2");
sy.start();
sy2.start();
}
}
class Sy extends Thread {
private int flag ;
static Object x1 = new Object();
static Object x2 = new Object();
public Sy(int flag) {
this.flag = flag;
}
@Override
public void run() {
System.out.println(flag);
try {
if (flag == 0) {
synchronized (x1) {
System.out.println(flag+" x1");
Thread.sleep(1000);
// x1.wait(1000);
synchronized (x2) {
System.out.println(flag+" x2");
}
System.out.println(flag+" x1 x2");
}
}
if(flag == 1) {
synchronized (x2) {
System.out.println(flag+" x2");
Thread.sleep(100);
// x2.wait(100);
synchronized (x1) {
System.out.println(flag+" x1");
}
System.out.println(flag+" x1 x2");
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
このプログラムが実行されると、x 1はx 2を待っているため、x 2はx 1を待っているため、硬直状態になり、デッドロックが発生する.
この時、少し修正して、私はThreadクラスのsleep方法を使わないで、Objectクラスのwait方法を変えて、この時デッドロックが発生しないで、これもwaitとsleepの違いを検証しました:
waitメソッドは現在のオブジェクトのロックを解放しますが、sleepメソッドは現在のオブジェクトのロックを解放しません.
package multithread_learning;
/**
* @author xiaohao
* @date :Aug 7, 2017 3:11:26 PM
* @version 1.0
*/
public class TestSynchronized {
public static void main(String[] args) {
// TODO Auto-generated method stub
Sy sy = new Sy(0);
Sy sy2 = new Sy(1);
sy.setName("t1");
sy2.setName("t2");
sy.start();
sy2.start();
}
}
class Sy extends Thread {
private int flag ;
static Object x1 = new Object();
static Object x2 = new Object();
public Sy(int flag) {
this.flag = flag;
}
@Override
public void run() {
System.out.println(flag);
try {
if (flag == 0) {
synchronized (x1) {
System.out.println(flag+" x1");
// Thread.sleep(1000);
x1.wait(1000);
synchronized (x2) {
System.out.println(flag+" x2");
}
System.out.println(flag+" x1 x2");
}
}
if(flag == 1) {
synchronized (x2) {
System.out.println(flag+" x2");
// Thread.sleep(100);
x2.wait(100);
synchronized (x1) {
System.out.println(flag+" x1");
}
System.out.println(flag+" x1 x2");
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
0
1
1 x2
0 x1
1 x1
1 x1 x2
0 x2
0 x1 x2
スレッドt 1とt 2は、どちらのスレッドが先に実行されるとは限らないので、3,4行目の位置が入れ替わる場合があるかもしれないが、flag=0の場合、x 1オブジェクトwaitの時間は1000 msであり、このときx 1のオブジェクトロックが解放され、終了を待つ(つまり1000 ms以内)、flag=1の条件がx 2およびx 1オブジェクトを実行済みとなり、このときflag=0はx 1オブジェクトを実行し続け、つまり、常に1リリース、0リリースです.
ただしwait()メソッドとnotify()メソッドは同期コードブロックにしか入れられません.同期コードブロックで使用しない場合、コンパイル時にエラーは発生しませんが、実行時にjava.lang.I llegalMonitorStateException異常が放出されます.