Java 中的同步方法和同步块有什么区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1149928/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the difference between a synchronized method and synchronized block in Java?
提问by Geek
What is the difference between a synchronized method and synchronized block in Java ?
Java 中的同步方法和同步块有什么区别?
I have been searching the answer on the Net, people seem to be so unsure about this one :-(
我一直在网上搜索答案,人们似乎对此不太确定:-(
My take would be there is no difference between the two, except that the synch block might be more localized in scope and hence the lock will be of lesser time ??
我的看法是两者之间没有区别,除了同步块可能在范围内更加本地化,因此锁的时间会更短??
And in case of Lock on a static method, on what is the Lock taken ? What is the meaning of a Lock on Class ?
在静态方法上锁定的情况下,锁定是什么?锁定 Class 是什么意思?
采纳答案by notnoop
A synchronized method uses the method receiver as a lock (i.e. this
for non static methods, and the enclosing class for static methods). Synchronized
blocks uses the expression as a lock.
同步方法使用方法接收器作为锁(即this
对于非静态方法,以及静态方法的封闭类)。 Synchronized
blocks 使用表达式作为锁。
So the following two methods are equivalent from locking prospective:
所以从锁定的角度来看,以下两种方法是等效的:
synchronized void mymethod() { ... }
void mymethod() {
synchronized (this) { ... }
}
For static methods, the class will be locked:
对于静态方法,类将被锁定:
class MyClass {
synchronized static mystatic() { ... }
static mystaticeq() {
syncrhonized (MyClass.class) { ... }
}
}
For synchronized blocks, you can use any non-null
object as a lock:
对于同步块,您可以使用任何非null
对象作为锁:
synchronized (mymap) {
mymap.put(..., ...);
}
Lock scope
锁定范围
For synchronized methods, the lock will be held throughout the method scope, while in the synchronized
block, the lock is held only during that block scope (otherwise known as critical section). In practice, the JVM is permitted to optimize by removing some operations out of the synchronized
block execution if it can prove that it can be done safely.
对于同步方法,锁将在整个方法范围内持有,而在synchronized
块中,锁仅在该块范围内(也称为临界区)持有。在实践中,如果 JVMsynchronized
可以证明可以安全地完成,则允许 JVM 通过从块执行中删除一些操作来进行优化。
回答by Henning
Yes, that is one difference. The other is that you can acquire a lock on other objects than this
.
是的,这是一个区别。另一个是您可以获取对其他对象的锁而不是this
.
回答by jqno
A synchronized method is shorthand. This:
同步方法是速记。这个:
class Something {
public synchronized void doSomething() {
...
}
public static synchronized void doSomethingStatic() {
...
}
}
is, for all intents and purposes, equivalent to this:
就所有意图和目的而言,等同于:
class Something {
public void doSomething() {
synchronized(this) {
...
}
}
public static void doSomethingStatic() {
synchronized(Something.class) {
...
}
}
}
(Where Something.class
is the class object for the class Something
.)
(Something.class
类的类对象在哪里Something
。)
So indeed, with a synchronized block, you can be more specific about your lock, and more fine-grained about when you want to use it, but other than that there's no difference.
因此,确实,使用同步块,您可以更具体地了解您的锁,并更细粒度地了解何时要使用它,但除此之外没有任何区别。
回答by madlep
A synchronized method locks on the object instance the method is contained in.
同步方法锁定包含该方法的对象实例。
Where as a synchronized block can lock on ANY object - typically a mutex obect defined as an instance variable. This allows more control over what locks are in operation.
同步块可以锁定任何对象 - 通常是定义为实例变量的互斥对象。这允许更多地控制正在运行的锁。
回答by Michael Aaron Safyan
The key difference is this: if you declare a method to be synchronized, then the entire body of the method becomes synchronized; if you use the synchronized block, however, then you can surround just the "critical section" of the method in the synchronized block, while leaving the rest of the method out of the block.
关键的区别在于:如果你声明一个方法是同步的,那么整个方法体就会变成同步的;但是,如果您使用同步块,那么您可以只将方法的“临界区”包围在同步块中,而将方法的其余部分留在块之外。
If the entire method is part of the critical section, then there effectively is no difference. If that is not the case, then you should use a synchronized block around just the critical section. The more statements you have in a synchronized block, the less overall parallelism you get, so you want to keep those to the minimum.
如果整个方法是临界区的一部分,那么实际上没有区别。如果不是这种情况,那么您应该只在临界区周围使用同步块。同步块中的语句越多,获得的整体并行度就越低,因此您希望将它们保持在最低限度。
回答by Ravindra babu
My take would be there is no difference between the two, except that the synch block might be more localized in scope and hence the lock will be of lesser time ??
我的看法是两者之间没有区别,除了同步块可能在范围内更加本地化,因此锁的时间会更短??
Yes. You are right. Unlike synchronized
methods, synchronized statements must specify the object that provides the intrinsic lock.
是的。你是对的。与synchronized
方法不同,同步语句必须指定提供内在锁的对象。
Example from java tutorial:
java教程中的示例:
public void addName(String name) {
synchronized(this) {
lastName = name;
nameCount++;
}
nameList.add(name);
}
Synchronized statements are also useful for improving concurrency with fine-grained synchronization. You can find good example on same tutorial page for below use case.
同步语句对于通过细粒度同步提高并发性也很有用。您可以在以下用例的同一教程页面上找到很好的示例。
Suppose, for example, class MsLunch
has two instance fields, c1 and c2, that are never used together. All updates of these fields must be synchronized
, but there's no reason to prevent an update of c1 from being interleaved with an update of c2 — and doing so reduces concurrency by creating unnecessary blocking. Instead of using synchronized methods or otherwise using the lock associated with this, we create two objects solely to provide locks.
例如,假设 classMsLunch
有两个实例字段 c1 和 c2,它们从不一起使用。这些字段的所有更新都必须是synchronized
,但没有理由阻止 c1 的更新与 c2 的更新交错 — 这样做会通过创建不必要的阻塞来减少并发性。我们不使用同步方法或以其他方式使用与此关联的锁,而是单独创建两个对象来提供锁。
And in case of Lock on a static method, on what is the Lock taken ? What is the meaning of a Lock on Class ?
在静态方法上锁定的情况下,锁定是什么?锁定 Class 是什么意思?
In this case, the thread acquires the intrinsic lock for the Class object associated with the class. Thus access to class's static fields is controlled by a lock that's distinct from the lock for any instance of the class.
在这种情况下,线程获取与类关联的 Class 对象的内在锁。因此,对类的静态字段的访问由与类的任何实例的锁不同的锁控制。
When you make a method as synchronized( non static
) :
当您将方法设为同步(非static
)时:
It is not possible for two invocations of synchronized
methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
synchronized
同一对象上的两次方法调用不可能交错。当一个线程正在为一个对象执行同步方法时,所有其他调用同一个对象的同步方法的线程都会阻塞(挂起执行),直到第一个线程完成对对象的处理。
If you make a method as static synchronized
:
如果您将方法设为static synchronized
:
It is not possible for two invocations of static synchronized
methods on different objects of same class to interleave. When one thread is executing a static synchronized
method for an object of Class A, all other threads that invoke static synchronized
methods on any of objects of Class A block (suspend execution) until the first thread is done with the method execution.
static synchronized
对同一类的不同对象的两次方法调用不可能交错。当一个线程正在执行static synchronized
A 类对象的static synchronized
方法时,调用A 类任何对象上的方法的所有其他线程都会阻塞(挂起执行),直到第一个线程完成该方法的执行。
You find better alternatives to synchronization in this SE question:
您可以在此 SE 问题中找到更好的同步替代方法: