【发布时间】:2010-04-28 09:43:41
【问题描述】:
synchronized方法和synchronized语句有什么区别?
如果可能,请用一个例子来说明清楚。
【问题讨论】:
-
我觉得PartlyCloudy's answer是最简洁的。
标签: java multithreading concurrency synchronization
synchronized方法和synchronized语句有什么区别?
如果可能,请用一个例子来说明清楚。
【问题讨论】:
标签: java multithreading concurrency synchronization
同步方法会锁定与类(即“this”)或类(如果是静态方法)的实例关联的监视器,并阻止其他人这样做,直到从该方法返回。同步块可以锁定任何监视器(您告诉它哪个),并且可以具有小于 encolsing 方法的范围。
如果同步块最终不等同于方法的整个范围和/或如果它们锁定的东西比实例(或静态的类)不那么严格,则首选同步块。
【讨论】:
JLS 引述(包括示例):
synchronized Statement
synchronized语句代表正在执行的线程获取互斥锁,执行一个块,然后释放锁。当执行线程拥有锁时,没有其他线程可以获取锁。
synchronized Methods
synchronized方法在执行之前获取监视器。对于类 (static) 方法,使用与方法类的Class对象关联的监视器。对于实例方法,使用与this(调用该方法的对象)关联的监视器。这些与
synchronized语句可以使用的锁相同;因此,代码:class Test { int count; synchronized void bump() { count++; } static int classCount; static synchronized void classBump() { classCount++; } }效果完全一样:
class BumpTest { int count; void bump() { synchronized (this) { count++; } } static int classCount; static void classBump() { try { synchronized (Class.forName("BumpTest")) { classCount++; } } catch (ClassNotFoundException e) { ... } } }
那么它们有何不同?
引用Effective Java 2nd Edition,第 67 条:避免过度同步:
作为一项规则,您应该在
synchronized区域内做尽可能少的工作。
方法的synchronized 修饰符是一种语法糖,适用于许多但并非所有场景。这本书更详细地讨论了为什么你应该避免过度同步,但基本上通过使用synchronized 语句,你可以更好地控制synchronized 区域的边界(如果场景需要,你也可以选择你自己的锁)。
除非您的方法非常简单和/或您需要在方法的整个持续时间内获取this 锁(或者如果方法是static,则需要Class 对象锁),您应该使用@987654340 @ 语句将方法内的同步限制为仅在您需要时(即当您访问共享的可变数据时)。
【讨论】:
synchronized 方法是其主体自动封装在 synchronized 块中的方法。
因此,这是相等的:
public void foo()
{
synchronized (this)
{
bar();
}
}
public synchronized void foo()
{
bar();
}
【讨论】:
synchronized on 方法被锁定在 this 对象上。等于synchronized (this) {}
标准synchronized 被锁定在指定的对象/监视器上。使用synchronized (***) {},您可以选择用于锁定的对象。
【讨论】:
同步方法实际上是将函数的整个主体放在同步块中。同步块的优点是您可以将同步块应用于函数中的几个选择语句,而不是整个函数。通常,最好使同步块尽可能短,因为在同步块中花费的时间可能会阻止其他线程执行有意义的工作。另一个区别是,您可以在使用同步块时指定要对其应用锁的特定对象,而使用同步方法时,对象本身会自动用作执行同步的锁。
【讨论】: