5

下面的代码会发生什么?同步有效吗?这是一道面试题。

class T
{
    public static void main(String args[])
    {
        Object myObject = new Object();
        synchronized (myObject)
        {
            myObject = new Object();
        } // end sync
    }
}
4

6 回答 6

4

每次进入同步块时,都会在不同的对象上同步。大多数情况下,除了让你感到困惑之外,这不会做任何事情,但是两个线程看到同一个对象并等待的可能性很小。

出于这个原因,如果您正在同步的字段不是final.

于 2012-06-21T08:59:44.457 回答
1

它仍然释放获取的同一个监视器,但是任何其他也使用锁定的代码myObject(这里不可能,因为它是一个局部变量,使得同步基本上毫无意义)将开始使用新对象。

不要忘记同步应用于对象(或者更确切地说,与对象关联的监视器) - 而不是变量。获取/释放的监视器仅取决于到达同步块开始时的表达式值。在同步块结束时不会重新计算表达式。

于 2012-06-21T08:58:47.160 回答
0

不,它不起作用。每当有新线程进入时,myObject就会创建一个新线程。特别是现在这myObject是一个局部变量!

即使myObject是类成员,它也不起作用,因为您将更改要锁定的对象。有关详细说明,请参阅有关非最终字段同步的问题。

于 2012-06-21T08:59:08.670 回答
0

我看不出这段代码背后的原因,因为对象没有被任何线程共享。在任何情况下,删除同步块都不会影响实际结果。它只会让你的代码运行得更快

于 2012-06-21T09:03:42.023 回答
0

你需要先获取myObject的锁,如果这个锁被阻塞了,你必须等到锁被释放。

同步需要多线程环境。但是您的代码似乎与并发无关。所以我很遗憾地告诉您,没有任何事情会发生。

于 2012-06-21T09:06:05.423 回答
0

运行代码并分析结果。

public class Test {
    static Foo o = new Foo(0);
    static class Foo {
        private int i = 0;
        Foo(int i) {
            this.i = i;
        }
        public void addOnce() {
            this.i++;
        }
        public String toString() {
            return String.valueOf(i);
        }
    }
    public static void main(String args[]) {
        test1();
        try {Thread.sleep(10000);} catch (Exception e) {}
        test2();
    }
    public static void test1() {
        Runnable r = new Runnable() {
            public void run() {
                synchronized (o) {
                    System.out.println("1------>"+o);
                    o = new Foo(1);
                    try {Thread.sleep(3000);} catch (Exception e) {}
                    System.out.println("1------>"+o);
                }
            }
        };
        new Thread(r).start();
        new Thread(r).start();
    }
    public static void test2() {
        Runnable r = new Runnable() {
            public void run() {
                synchronized (o) {
                    System.out.println("2------>"+o);
                    o.addOnce();
                    try {Thread.sleep(3000);} catch (Exception e) {}
                    System.out.println("2------>"+o);
                }
            }
        };
        new Thread(r).start();
        new Thread(r).start();
    }
}
于 2012-06-21T09:23:56.890 回答