Java中的同步方法和同步块有什么区别?
Java 中的同步方法和同步块有什么区别?
我一直在网上搜索答案,人们似乎对此非常不确定:-(
我的看法是两者之间没有区别,除了同步块的范围可能更本地化,因此锁将时间更短?
如果对静态方法加锁,那么对类加锁的含义是什么?
What is the difference between a synchronized method and synchronized block in 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 ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
同步方法使用方法接收器作为锁(即非静态方法的
this
和静态方法的封闭类)。Synchronized
块使用表达式作为锁。因此,从锁定的角度来看,以下两种方法是等效的:
对于静态方法,类将被锁定:
对于同步块,您可以使用任何非
null
对象作为锁:锁定范围< /b>
对于同步方法,锁将在整个方法范围内保持,而在
synchronized
块中,锁仅在该块范围内(也称为临界区)保持。 在实践中,如果 JVM 能够证明可以安全地完成,则允许通过从同步块执行中删除一些操作来进行优化。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.So the following two methods are equivalent from locking prospective:
For static methods, the class will be locked:
For synchronized blocks, you can use any non-
null
object as a lock: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 thesynchronized
block execution if it can prove that it can be done safely.同步方法是简写。 从所有意图和目的来看,这
相当于:(
其中
Something.class
是类Something
的类对象。)确实如此,使用同步块,您可以更具体地了解您的锁,并更详细地了解何时要使用它,但除此之外没有任何区别。
A synchronized method is shorthand. This:
is, for all intents and purposes, equivalent to this:
(Where
Something.class
is the class object for the classSomething
.)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.
是的,这是一个区别。 另一个是您可以获取除
this
之外的其他对象的锁。Yes, that is one difference. The other is that you can acquire a lock on other objects than
this
.关键区别在于:如果您声明一个方法要同步,那么该方法的整个主体都会变为同步; 但是,如果使用同步块,则可以仅将方法的“关键部分”包围在同步块中,而将方法的其余部分保留在块之外。
如果整个方法是关键部分的一部分,那么实际上没有区别。 如果情况并非如此,那么您应该仅在关键部分周围使用同步块。 同步块中的语句越多,获得的整体并行性就越少,因此您希望将这些语句保持在最低限度。
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.
同步方法锁定该方法所在的对象实例。
同步块可以锁定任何对象 - 通常是定义为实例变量的互斥对象。 这可以更好地控制正在运行的锁。
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.
是的。 你是对的。 与
synchronized
方法不同,synchronized 语句必须指定提供内在锁的对象。java 教程中的示例:
同步语句对于通过细粒度同步提高并发性也很有用。 您可以在同一教程页面上找到以下用例的好示例。
例如,假设类
MsLunch
有两个实例字段 c1 和 c2,它们从不一起使用。 这些字段的所有更新都必须同步
,但是没有理由阻止 c1 的更新与 c2 的更新交错 — 这样做会通过创建不必要的阻塞来减少并发性。 我们不使用同步方法或以其他方式使用与此相关的锁,而是创建两个对象来提供锁。在这种情况下,线程获取与该类关联的 Class 对象的固有锁。 因此,对类的静态字段的访问是由与该类的任何实例的锁不同的锁控制的。
当您将方法设置为 同步 (非
static
) :同一对象上的两次同步方法调用不可能交错。 当一个线程正在执行对象的同步方法时,调用同一对象的同步方法的所有其他线程都会阻塞(挂起执行),直到第一个线程完成该对象。
如果将方法设置为静态同步方法:
同一类的不同对象上的静态同步方法的两次调用不可能交错。 当一个线程正在为 A 类对象执行静态同步方法时,所有其他对 A 类对象调用静态同步方法的线程都会阻塞(暂停执行)直到第一个线程完成方法执行。
您可以在此SE问题中找到同步的更好替代方案:
避免在Java中同步(this)?< /a>
Yes. You are right. Unlike
synchronized
methods, synchronized statements must specify the object that provides the intrinsic lock.Example from java tutorial:
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 besynchronized
, 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.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.
When you make a method as synchronized ( non
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.If you make a method as
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 astatic synchronized
method for an object of Class A, all other threads that invokestatic synchronized
methods on any of objects of Class A block (suspend execution) until the first thread is done with the method execution.You find better alternatives to synchronization in this SE question:
Avoid synchronized(this) in Java?