如果在线程同步块中将被同步对象修改会发生什么情况?
import java.util.concurrent.TimeUnit;
public class Main
{
public static void main(String[] args) {
Object object = new Object() ;
Syn syn1 = new Syn(object) ;
Syn syn2 = new Syn(object) ;
Thread thread = new Thread(syn1) ;
thread.start() ;
thread = new Thread(syn2) ;
thread.start() ;
}
}
class Syn implements Runnable
{
private Object object ;
public Syn(Object object) {
this.object = object;
}
@Override
public void run() {
synchronized (object)
{
object = new Object() ;
try {
System.out.println("in sleep " + Thread.currentThread().getName());
TimeUnit.SECONDS.sleep(1);
System.out.println("out sleep" + Thread.currentThread().getName());
}
catch (Exception e)
{
System.err.println(e);
}
}
}
}
我用上面的程序测试发现在同步块中修改了object并不会影响两条线程的互斥, 那么为什么推荐使用不可变对象或者专用的锁来实现线程的互斥呢?
これを実行します:
リーリー取得される結果は、期待したものと一致しない可能性があります。実際に同期ロックされるのは、オブジェクト参照が指す内容です。
オブジェクト参照を新しい Object() に再バインドしても、ロックされたコンテンツは変更されません。つまり、syn2 の
サーフェス内のオブジェクトが指すコンテンツはまだロックされており、実行を続行するには syn1 の同期ブロックが終了するまで待つ必要があるため、 (syn1, syn2)
が順次実行されます。これにより、コードの読み取りと保守が困難になります。
そのため、Java では、同期が必要なオブジェクトが他のオブジェクトに再バインドされないように、final を使用して変更することをお勧めします。
ここでの object=new Object(); は役に立ちません。ここで変更した現在のオブジェクトのオブジェクト参照は、スレッドが初めて実行するときは確かに相互排他を反映しますが、2 回目には反映されません。実行されました。
リーリーこれらは自分で書くことができます:
Syn でオブジェクトを宣言したため、各 Syn インスタンスが保持するオブジェクトが同じではなくなったため、問題があると考えられます。私が使用した解決策は次のとおりです。
リーリー