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

时间:2018-06-15 21:03:43

标签: java critical-section

我试图弄清楚,同步块和同步函数之间的区别实际上是什么。本规范运作完美,因为它避免了关键部分的错误

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()代替它,它就无法正常/正常地工作。

2 个答案:

答案 0 :(得分:11)

根据JLS 8.4.3.6. synchronized Methods

  

同步方法在执行之前获取监视器(第17.1节)。

     

对于类(静态)方法,使用与方法类的Class对象关联的监视器。

     

对于实例方法,使用与此关联的监视器(调用该方法的对象)。

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

当您创建实例方法 synchronized时,您只在该实例(this引用)上进行同步。

答案 1 :(得分:2)

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

synchronized (getClass()) { ... }在类上同步,因此在两个Thread实例中,一次只能有一个进入块。

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

同步方法在实例上为普通实例方法同步,在静态方法的类对象上同步。

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