synchronized
方法和synchronized
语句有什么区别?
如果可以的话,请举个例子来让它更清楚。
同步方法会锁定与类实例(即“this”)或类(如果是静态方法)关联的监视器,并阻止其他人这样做,直到该方法返回为止。同步块可以锁定任何监视器(您告诉它哪个),并且可以具有比封闭方法更小的范围。
如果同步块最终不等于方法的整个范围,和/或如果它们锁定的东西比实例(或类,如果是静态的)不那么严格,则首选同步块。
引自JLS(包括示例):
synchronized
声明语句代表执行线程获取互斥锁,执行一个块,然后释放锁。当执行线程拥有锁时,其他线程无法获取该锁。synchronized
synchronized
方法方法在执行之前获取监视器。对于类 (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 第 2 版,第 67 条:避免过度同步:
通常,您应该在
区域内做尽可能少的工作。synchronized
方法的
synchronized
修饰符本身就是一种语法糖,适用于许多但并非所有场景。本书更深入地讨论了为什么应该避免过度同步,但基本上通过使用 synchronized
语句,您可以更好地控制 synchronized
区域的边界(如果场景需要,您也可以选择您自己的锁)。
除非您的方法非常简单和/或您需要在方法的整个持续时间内获取
this
锁(如果方法是 Class
,则需要获取 static
对象锁),否则您应该使用 synchronized
语句将方法内的同步限制为仅在您需要时(即,当您访问共享的可变数据时)。
synchronized
方法是一种其主体自动封装在synchronized
块中的方法。
因此,这是相等的:
public void foo()
{
synchronized (this)
{
bar();
}
}
public synchronized void foo()
{
bar();
}
synchronized
on 方法被锁定在 this
对象上。等于synchronized (this) {}
标准
synchronized
锁定在指定对象/监视器上。使用 synchronized (***) {}
,您可以选择用于锁定的对象。
同步方法实际上是将函数的整个主体放在同步块中的方法。同步块的优点是您可以将同步块仅应用于函数中的几个 select 语句,而不是应用于整个函数。一般来说,最好使同步块尽可能短,因为花费在同步块中的时间可能会阻止其他线程执行有意义的工作。另一个区别是,您可以在使用同步块时指定要应用锁的特定对象,而使用同步方法时,该对象本身会自动用作执行同步的锁。