下面这两个同步块是否互斥?

Object obj=new Object();
Object obj2=obj;
synchronized(obj){}
synchronized(obj2){}

又如果这样呢?

Object obj=new Object();
synchronized(obj){}
obj=new Object();
synchronized(obj){}
阅读 3.1k
3 个回答

上面两个 synchronized 块是互斥的.
所以基于这种锁对象可能被误用的情况, 建议用单独的 final 对象做锁, 而不要用与业务相关的变量:

final Object lock = new Object();

锁这个标记是在 对象的Header的markword中存在的,是和一个对象绑定的,而不是和对象的引用绑定,所以第一个问题是互斥的,你的第二个问题有问题,因为你写synchronized(obj){}的时候,一般是以内部类的形式写在runnable或者Thread中,但是内部类引用的外部变量就必须是final的,而你这个obj都变了,就不是final,所以这段代码你是咋写出来的?

针对问题:如果多个线程在并发执行执行拥有相同锁的同步块synchronized(obj){}时,锁对象obj被另一个线程给修改了指向,这个同步是否会失效?我有测试过这种情况没有失效,可能是因为即便obj引用指向变了,当前还没有执行完的同步块之间还是互斥的,因为对象还没有被回收还在使用中。如果只有一个同步块没有执行完,修改obj指向后,又执行了一个synchronized(obj){},这个时候它们是不是互斥的呢?

测试代码:

    static Object obj=new String("a");
    public static void main(String[] args) throws InterruptedException {
        class a extends Thread{
            @Override
            public void run() {
                synchronized(obj){
                    for (int i = 0; i < 10000; i++) {
                        if(i%10==0)System.out.println(obj+",0");
                    }
                }
            }
        }
        new a().start();
        Thread.sleep(10);
        obj=new String("b");
        class b extends Thread{
            @Override
            public void run() {
                synchronized(obj){
                    for (int i = 0; i < 10000; i++) {
                        if(i%10==0)System.out.println(obj+",1");
                    }
                }
            }
        }
        new b().start();
    }

测试结果:两个线程输出有交叉,同步确实会失效

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题