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

发布于 2022-09-03 00:30:27 字数 979 浏览 15 评论 0

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

烟柳画桥 2022-09-10 00:30:27

这样做:

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

得到的结果可能和你预期的不一致,sync锁住的实际上是object这个引用所指向的内容。当你把
object这个引用重新绑给一个new Object() 时,被锁住的内容不会发生改变。也就是说syn2里
面的object指向的内容依然被锁住,需要等到syn1里的sync块结束才能继续执行,所以他们(syn1, syn2)
是顺序执行的。这给代码的阅读和维护造成了困难。
所以Java建议你使用final来修饰这个需要sync的对象,保证其不会重新绑定给其他对象。

_畞蕅 2022-09-10 00:30:27

你这里object=new Object();是没用的,你这里改变的当前对象的object引用,线程执行第一次确实能体现出互斥,但是执行第二次就体现不出来了。
你可以自己这些写:

while(true){
    synchronized(object){
        //todo
    }
}
别再吹冷风 2022-09-10 00:30:27

你在Syn中声明了object,导致每个Syn实例所持有的object并不是同一个,所以你觉得有问题,我用的方案如下:

class Sync implements Runnable{
    private static Object object;
    //构造方法略
    @Override
    public void run(){
        synchronized(Object.class){
            //
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文