如果在线程同步块中将被同步对象修改会发生什么情况?
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();는 쓸모가 없습니다. 여기서 변경한 현재 개체의 개체 참조는 실제로 스레드가 처음 실행할 때 상호 배제를 반영할 수 있지만 두 번째에는 반영되지 않습니다. 실행됩니다.
으아악직접 작성할 수 있습니다.
Syn에서 개체를 선언했는데, 이로 인해 각 Syn 인스턴스가 서로 다른 개체를 보유하게 되었습니다. 따라서 제가 사용한 해결 방법은 다음과 같습니다.
으아악