如果在线程同步块中将被同步对象修改会发生什么情况?
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并不会影响两条线程的互斥, 那么为什么推荐使用不可变对象或者专用的锁来实现线程的互斥呢?
這樣做:
得到的結果可能和你預期的不一致,sync鎖住的其實是object這個引用所指向的內容。當你把
object這個引用重新綁定到一個new Object() 時,被鎖住的內容就不會改變。也就是說syn2裡
面的object指向的內容依然被鎖住,需要等到syn1裡的sync塊結束才能繼續執行,所以他們(syn1, syn2)
是順序執行的。這給程式碼的閱讀和維護造成了困難。
所以Java建議你使用final來修飾這個需要sync的對象,保證其不會重新綁定給其他對象。
你這裡object=new Object();是沒用的,你這裡改變的目前物件的object引用,執行緒執行第一次確實能體現出互斥,但是執行第二次就體現不出來了。
你可以自己這些寫:
你在Syn中聲明了object,導致每個Syn實例所持有的object並不是同一個,所以你覺得有問題,我用的方案如下: