Java中的同步方法和同步块有什么区别?
我在网上搜索了答案,人们似乎对这个问题不太确定 :-(
我的看法是两者之间没有区别, 只是同步块的范围更局部,因此锁定时间更短 ??
在静态方法中锁定时,锁定对象是什么?什么是类锁?
Java中的同步方法和同步块有什么区别?
我在网上搜索了答案,人们似乎对这个问题不太确定 :-(
我的看法是两者之间没有区别, 只是同步块的范围更局部,因此锁定时间更短 ??
在静态方法中锁定时,锁定对象是什么?什么是类锁?
同步方法使用方法接收者作为锁(即非静态方法使用this
,而静态方法使用封闭类)。synchronized
块使用表达式作为锁。
因此,下面两个方法在锁定方面是等效的:
synchronized void mymethod() { ... }
void mymethod() {
synchronized (this) { ... }
}
对于静态方法,类将被锁定:class MyClass {
synchronized static mystatic() { ... }
static mystaticeq() {
syncrhonized (MyClass.class) { ... }
}
}
同步块中,您可以使用任何非null
对象作为锁:
synchronized (mymap) {
mymap.put(..., ...);
}
锁范围
对于同步方法,锁将在整个方法范围内保持,而在 synchronized
块中,锁仅在该块的范围内保持(也称为临界区)。实际上,如果JVM可以证明可以安全地执行操作,则允许通过优化从 synchronized
块执行中删除一些操作。
同步方法是一种简写方式。这样写:
class Something {
public synchronized void doSomething() {
...
}
public static synchronized void doSomethingStatic() {
...
}
}
就所有意图而言,这与以下内容等同:
class Something {
public void doSomething() {
synchronized(this) {
...
}
}
public static void doSomethingStatic() {
synchronized(Something.class) {
...
}
}
}
(其中Something.class
是类Something
的类对象。)
因此,使用同步块时,您可以更具体地锁定并更精细地控制何时使用它,但除此之外没有任何区别。
是的,这是其中一个区别。另一个区别是你可以在除了this
之外的其他对象上获取锁。
同步方法会锁定包含该方法的对象实例。
而同步块可以锁定任何对象 - 通常是作为实例变量定义的互斥对象。这允许更多对正在运行的锁进行控制。
public void addName(String name) {
synchronized(this) {
lastName = name;
nameCount++;
}
nameList.add(name);
}
同步语句对于通过细粒度同步来提高并发性也非常有用。您可以在同一教程页面上找到以下用例的良好示例。
例如,假设类MsLunch
有两个实例字段和,它们从未同时使用。这些字段的所有更新都必须进行同步,但没有理由防止对的更新与对的更新交错 - 这样做会通过创建不必要的阻塞来降低并发性。相反,我们创建了两个对象,仅用于提供锁,而不是使用同步方法或以其他方式使用与此关联的锁。
在静态方法上锁定时,锁定的是什么?类上的锁有什么意义?
在这种情况下,线程获取与类相关联的Class对象的内部锁定。因此,对类的静态字段的访问受到与类的任何实例的锁定不同的锁定控制。
当您将方法设置为synchronized(非static
)时:
synchronized
方法在同一对象上的两次调用之间不可能交错执行。 当一个线程正在执行对象的 synchronized 方法时,所有尝试调用该对象上的 synchronized 方法的其他线程都会被阻塞,直到第一个线程完成为止。
如果您将方法声明为 static synchronized
:
不可能让同一类不同对象的两个static synchronized
方法调用交错执行。 当一个线程正在执行 Class A 对象的 static synchronized
方法时,所有尝试调用 Class A 的任何对象上的 static synchronized
方法的其他线程都会被阻塞,直到第一个线程完成此方法的执行。
在这个SE问题中,您可以找到更好的替代同步的方法: