Java - 同步块的工作方式与方法不同

Java - Synchronized block works differently than method

我想弄清楚,同步块和同步函数之间的区别到底是什么。此代码完美运行,因为它避免了关键部分中的错误

class ThreadSynchronous extends Thread {
static int m_count = 0;
String s;

ThreadSynchronous(String s) {
    this.s = s;
}

public void run() {
    synchronized (getClass()) {
        ...
    }
}
}

public class ThreadExample {
public static void main(String[] args) {
    Thread t1 = new ThreadSynchronous("Thread1: ");
    Thread t2 = new ThreadSynchronous("Thread2: ");
    t1.start();
    t2.start();

    try{
        t1.join();
        t2.join();
    } catch (InterruptedException e){
    }
}
}

但是如果我改用public synchronized void run(),它就不起作用equally/properly。

根据 JLS 8.4.3.6. synchronized Methods:

A synchronized method acquires a monitor (§17.1) before it executes.

For a class (static) method, the monitor associated with the Class object for the method's class is used.

For an instance method, the monitor associated with this (the object for which the method was invoked) is used.

synchronized (getClass()) 块中,您在 Class 对象上同步,因此 ThreadSynchronous 的所有实例都被序列化。

当您制作 实例方法 synchronized 时,您仅在该实例(this 引用)上进行同步。

两者在不同的对象上同步。

synchronized (getClass()) { ... } 在 class 上同步,所以在你的两个 Thread 实例中,一次只能有一个可以进入块。

另一方面,public synchronized void run() { ... }在实例上同步,因此两个实例都可以并行进入块。仅当单个实例被多个线程共享时,此块将只允许其中一个执行。

同步方法对于普通实例方法在实例上同步,对于静态方法在 class 对象上同步。

因此,如果您的 run() 方法可以重构为静态方法,那么 synchronized 方法关键字将为您提供 synchronized (getClass()) { ... } 行为。