Java 同期とスレッド
-
16-09-2019 - |
質問
Synchronized が期待どおりに動作しないという問題が発生しました。volatile キーワードも使用してみました。
共有オブジェクト:
public class ThreadValue {
private String caller;
private String value;
public ThreadValue( String caller, String value ) {
this.value = value;
this.caller = caller;
}
public synchronized String getValue() {
return this.caller + " " + this.value;
}
public synchronized void setValue( String caller, String value ) {
this.caller = caller;
this.value = value;
}
}
スレッド 1:
class CongoThread implements Runnable {
private ThreadValue v;
public CongoThread(ThreadValue v) {
this.v = v;
}
public void run() {
for (int i = 0; i < 10; i++) {
v.setValue( "congo", "cool" );
v.getValue();
}
}
}
スレッド 2:
class CongoThread implements Runnable {
private ThreadValue v;
public CongoThread(ThreadValue v) {
this.v = v;
}
public void run() {
for (int i = 0; i < 10; i++) {
v.setValue( "congo", "lame" );
v.getValue();
}
}
}
呼び出しクラス:
class TwoThreadsTest {
public static void main (String args[]) {
ThreadValue v = new ThreadValue("", "");
Thread congo = new Thread( new CongoThread( v ) );
Thread libya = new Thread( new LibyaThread( v ) );
libya.start();
congo.start();
}
}
時々私は得る "In Libya Thread congo cool"
それは決してあってはならないことです。私が期待するのは次のことだけです:
"In Libya Thread libya awesome"
"In Congo Thread congo cool"
それらが混在することは期待できません。
解決
何が起こるかは次のとおりです。
- スレッド 1 が値を設定します
- スレッド 2 が値を設定します
- スレッド 1 は、スレッド 2 によって設定された値を読み取ります。
これを修正するには、両方のスレッドの get/set 関数呼び出しを保護する 1 つのロック オブジェクトが必要です。これを行う最善の方法は、設定と取得の両方を行う追加の同期メソッドを作成することです。ただし、それが望ましくない場合もあります。その場合、両方のスレッドにロック オブジェクトを与えます。それはただの普通のオブジェクトです。その後、それを同期ブロックで使用します。
各スレッドの実装は次のようになります。正確に同じオブジェクトを持つ必要があることに注意してください。
Object lockObject = new Object();
Thread t1 = new CongroThread(v, lockObject);
Thread t2 = new LibyaThread(v, lockObject);
...
class CongoThread implements Runnable {
private ThreadValue v;
private Object lockObject;
public CongoThread(ThreadValue v, Object lockObject) {
this.v = v;
this.lockObject = lockObject,
}
public void run() {
for (int i = 0; i < 10; i++) {
synchronized(lockObject)
{
v.setValue( "congo", "lame" );
v.getValue();
}
}
}
}
他のヒント
あなただけの個別getValue
とsetValue
へのアクセスを同期していない2-ライナー
v.setValue( "congo", ..);
v.getValue();
そして、もちろん、2つのスレッドが1のsetValue
とgetValue
間で交錯する。
あなたはSystem.out.print呼び出しをsynchronzeましたか?同期がなければ、彼らはスレッドセーフですが、正しい順序で発光しないことがあります。
synchronzied(System.out) {
System.out.print(....);
System.out.flush();
}
所属していません StackOverflow