Java 同步锁定 Class,不是对象?

Java synchronized locking Class, not Object?

最近读了 Bruce Eckel (Thinking in Java),发现了一些问题:block synchronized(Object) locking Class!不是此 Class 的对象。这段代码证明了上面提到的:

public class Main {

    public static void main(String[] args) {
        Sync s = new Sync();
        new Thread(new Runnable() {
            @Override
            public void run() {
                s.go();
            }
        }, "First").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                s.go();
            }
        }, "Second").start();
    }
}

class Sync {

    private Writer w1, w2;

    public Sync() {
        w1 = new Writer();
        w2 = new Writer();
    }

    public void go() {
        synchronized (w2) {
            w1.log(Thread.currentThread().getName() + "...1");
            //!All threads must performance parallel, but they do it consistently.
            w2.log(Thread.currentThread().getName() + "...2");
            //All threads must performance parallel, and they do it.
        }
    }
}

class Writer {
    public void log(Object obj) {
        for (int i = 0; i < 5; i++) {
            lgn(obj);
            try {
                TimeUnit.MILLISECONDS.sleep(750);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

我已经锁定了w2,但是锁定得到了w2,而且!! w1。为什么? w1 和 w2 是不同的对象!他们为什么锁在一起?

但是所有消息来源都在谈论锁定同步对象,而不是 Class!如果我弄错了,你能帮我理解它是如何工作的吗?

输出

First...1
First...1
First...1
First...1
First...1
First...2
First...2
First...2
First...2
First...2
Second...1
Second...1
Second...1
Second...1
Second...1
Second...2
Second...2
Second...2
Second...2
Second...2

预期输出

First...1
Second...1
First...1
Second...1
First...1
Second...1
First...1
Second...1
First...1
Second...1
First...2
First...2
First...2
First...2
First...2
Second...2
Second...2
Second...2
Second...2
Second...2

P.S 对不起我的英语(

synchronized (w2) 表示我们用 w2 创建一个锁,而不是锁定对象 w2。您可以使用任何其他对象创建一个锁,并且同步块中的代码仍然被锁定。

class Sync {

    private Writer w1, w2;
    private Object whatEver;

    public Sync() {
        w1 = new Writer();
        w2 = new Writer();
        whatEver = new Object();
    }

    public void go() {
        synchronized (whatEver) {
            w1.log(Thread.currentThread().getName() + "...1");
            //!All threads must performance parallel, but they do it consistently.
            w2.log(Thread.currentThread().getName() + "...2");
            //All threads must performance parallel, and they do it.
        }
    }
}