java-se - java在线程同步块中修改同步对象会有什么后果?
大家讲道理
大家讲道理 2017-04-18 09:22:44
0
3
510

如果在线程同步块中将被同步对象修改会发生什么情况?

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并不会影响两条线程的互斥, 那么为什么推荐使用不可变对象或者专用的锁来实现线程的互斥呢?

大家讲道理
大家讲道理

光阴似箭催人老,日月如移越少年。

全部回覆(3)
洪涛

這樣做:

synchronized (object) {
        object = new Object() ;
        //do something
}

得到的結果可能和你預期的不一致,sync鎖住的其實是object這個引用所指向的內容。當你把
object這個引用重新綁定到一個new Object() 時,被鎖住的內容就不會改變。也就是說syn2裡
面的object指向的內容依然被鎖住,需要等到syn1裡的sync塊結束才能繼續執行,所以他們(syn1, syn2)
是順序執行的。這給程式碼的閱讀和維護造成了困難。
所以Java建議你使用final來修飾這個需要sync的對象,保證其不會重新綁定給其他對象。

洪涛

你這裡object=new Object();是沒用的,你這裡改變的目前物件的object引用,執行緒執行第一次確實能體現出互斥,但是執行第二次就體現不出來了。
你可以自己這些寫:

while(true){
    synchronized(object){
        //todo
    }
}
小葫芦

你在Syn中聲明了object,導致每個Syn實例所持有的object並不是同一個,所以你覺得有問題,我用的方案如下:

class Sync implements Runnable{
    private static Object object;
    //构造方法略
    @Override
    public void run(){
        synchronized(Object.class){
            //
        }
    }
}
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板