Javaマルチスレッド探究-スレッド同期
6738 ワード
スレッド同期とは
スレッド同期は、複数のスレッドが同時に同じデータを操作することによるデータ破壊を解決することであり、前述したチケットの例のように、-1を売るチケットが現れ、問題が発生する
スレッド同期方式
1.synchronizedキーワード
1.1同期方法
便利な宣言にsynchronizedを加えると、この方法は同期され、毎回1つのスレッドだけが方法のコードを実行することができ、このスレッドが方法から離れていない場合、他のスレッドはブロック状態になるしかなく、データを操作する1回に1つのスレッドしかないことを保証します.
1.2. 同期コードブロック
同期コードブロックは同期方法とは異なり、同期コードブロックは一部のコードのみをロックします.これにより、メソッド全体よりもロック効率が高くなります.私たちのチケット販売プログラムでは主に最もtickeです.この操作は原子操作ではありません.各スレッドが印刷とtickeを実行することを保証しなければなりません.他のスレッドが入ってきて同期コードブロックを実行することを許可するにはロックが必要です.このロックはオブジェクトロックです.同期するスレッドについては、同期を保証するために必要なロックが一致しています.たとえば、次の例のオブジェクトロックはthisです.このthisはMyRunnableの参照です.1部しかありません.各スレッドが所有しているので、同期を行うことができます.
次のオブジェクトロックnew Object()を考えてみましょう.これにより、オブジェクトロックが追加されているにもかかわらず、スレッドが新しいObjectオブジェクトを所有している場合、このロックメカニズムは失効し、同期の役割を果たしません.
クラスロックは、オブジェクトロックの他に、コードブロックが存在する方法が静的方法である場合、synchronizedのロックはthisではなくクラスであるべきである.静的メソッドにはオブジェクトのthis参照がないことはよく知られていますが、次のプログラムはクラスロックです.
スレッド同期は、複数のスレッドが同時に同じデータを操作することによるデータ破壊を解決することであり、前述したチケットの例のように、-1を売るチケットが現れ、問題が発生する
スレッド同期方式
1.synchronizedキーワード
1.1同期方法
便利な宣言にsynchronizedを加えると、この方法は同期され、毎回1つのスレッドだけが方法のコードを実行することができ、このスレッドが方法から離れていない場合、他のスレッドはブロック状態になるしかなく、データを操作する1回に1つのスレッドしかないことを保証します.
class MyRunnable implements Runnable{
private int ticket = 100;
@Override
public void run(){
salseTicket();
}
public synchronized void salseTicket(){
while (true){
if(ticket > 0){
try {
Thread.sleep(5);
System.out.println(" "+Thread.currentThread().getName()+" sales "+ticket--);
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
break;
}
}
}
}
public class ThreadDemo {
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable();
Thread t1 = new Thread(runnable,"one");
Thread t2 = new Thread(runnable,"two");
Thread t3 = new Thread(runnable,"third");
Thread t4 = new Thread(runnable,"four");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
1.2. 同期コードブロック
同期コードブロックは同期方法とは異なり、同期コードブロックは一部のコードのみをロックします.これにより、メソッド全体よりもロック効率が高くなります.私たちのチケット販売プログラムでは主に最もtickeです.この操作は原子操作ではありません.各スレッドが印刷とtickeを実行することを保証しなければなりません.他のスレッドが入ってきて同期コードブロックを実行することを許可するにはロックが必要です.このロックはオブジェクトロックです.同期するスレッドについては、同期を保証するために必要なロックが一致しています.たとえば、次の例のオブジェクトロックはthisです.このthisはMyRunnableの参照です.1部しかありません.各スレッドが所有しているので、同期を行うことができます.
class MyRunnable implements Runnable {
private int ticket = 100;
@Override
public void run() {
salseTicket();
}
public void salseTicket() {
while (true) {
synchronized (this) {//
if (ticket > 0) {
try {
Thread.sleep(5);
System.out.println(" " + Thread.currentThread().getName() + " sales " + ticket--);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
break;
}
}
}
}
}
次のオブジェクトロックnew Object()を考えてみましょう.これにより、オブジェクトロックが追加されているにもかかわらず、スレッドが新しいObjectオブジェクトを所有している場合、このロックメカニズムは失効し、同期の役割を果たしません.
synchronized (new Object()) {
if (ticket > 0) {
try {
Thread.sleep(5);
System.out.println(" " + Thread.currentThread().getName() + " sales " + ticket--);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
break;
}
}
クラスロックは、オブジェクトロックの他に、コードブロックが存在する方法が静的方法である場合、synchronizedのロックはthisではなくクラスであるべきである.静的メソッドにはオブジェクトのthis参照がないことはよく知られていますが、次のプログラムはクラスロックです.
public static void salseTicket() {
while (true) {
synchronized (MyRunnable.class) {
if (ticket > 0) {
try {
Thread.sleep(5);
System.out.println(" " + Thread.currentThread().getName() + " sales " + ticket--);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
break;
}
}
}
}