我试图弄清楚,同步块和同步函数之间的区别实际上是什么。本规范运作完美,因为它避免了关键部分的错误
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()
代替它,它就无法正常/正常地工作。
答案 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()) { ... }
行为。