search

Home  >  Q&A  >  body text

java-se - java在线程同步块中修改同步对象会有什么后果?

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

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

大家讲道理大家讲道理2893 days ago516

reply all(3)I'll reply

  • PHP中文网

    PHP中文网2017-04-18 09:24:44

    Do this:

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

    The results obtained may not be consistent with what you expected. What sync locks is actually the content pointed to by the object reference. When you rebind the
    object reference to a new Object(), the locked content will not change. In other words, the content pointed to by the object in syn2 is still locked, and it needs to wait until the sync block in syn1 ends before execution can continue, so they (syn1, syn2) are executed sequentially. This makes it difficult to read and maintain the code.
    So Java recommends that you use final to modify the object that requires sync to ensure that it will not be rebound to other objects.

    reply
    0
  • PHP中文网

    PHP中文网2017-04-18 09:24:44

    Your object=new Object(); here is useless. The object reference of the current object you changed here can indeed reflect the mutual exclusion when the thread executes it for the first time, but it does not reflect it the second time it is executed.
    You can write these yourself:

    while(true){
        synchronized(object){
            //todo
        }
    }

    reply
    0
  • 高洛峰

    高洛峰2017-04-18 09:24:44

    You declared object in Syn, which causes each Syn instance to hold different objects. So you think there is a problem. The solution I used is as follows:

    class Sync implements Runnable{
        private static Object object;
        //构造方法略
        @Override
        public void run(){
            synchronized(Object.class){
                //
            }
        }
    }

    reply
    0
  • Cancelreply