Java 中的并发:同步静态方法
我想了解 Java 中静态方法的锁定是如何完成的。
假设我有以下类:据
class Foo {
private static int bar = 0;
public static synchronized void inc() { bar++; }
public synchronized int get() { return bar; }
我所知,当我调用 f.get()
时,线程获取对象 f
上的锁,当我执行 >Foo.inc()
线程获取类 Foo
上的锁。
我的问题是这两个调用如何相互同步? 调用静态方法是否也会获取所有实例化的锁,或者相反(这似乎更合理)?
编辑:
我的问题不是静态同步如何工作,而是静态和非静态方法如何相互同步。 即,我不希望两个线程同时调用 f.get()
和 Foo.inc()
,但这些方法获取不同的锁。我的问题是如何防止这种情况以及在上面的代码中是否可以防止这种情况。
I want to understand how locking is done on static methods in Java.
let's say I have the following class:
class Foo {
private static int bar = 0;
public static synchronized void inc() { bar++; }
public synchronized int get() { return bar; }
It's my understanding that when I call f.get()
, the thread acquires the lock on the object f
and when I do Foo.inc()
the thread acquires the lock on the class Foo
.
My question is how are the two calls synchronized in respect to each other?
Is calling a static method also acquires a lock on all instantiations, or the other way around (which seems more reasonable)?
EDIT:
My question isn't exactly how static synchronized
works, but how does static and non-static methods are synchronized with each other.
i.e., I don't want two threads to simultaneously call both f.get()
and Foo.inc()
, but these methods acquire different locks. My question is how is this preventable and is it prevented in the above code.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
静态和实例
synchronized
方法彼此不相关,因此您需要在它们之间应用一些额外的同步,如下所示:(尽管在本例中将
synchronized
保留在get()
没有意义,因为它不执行任何需要实例同步的操作)。注意死锁 - 由于此代码获取多个锁,因此它应该以一致的顺序执行,即其他同步静态方法不应尝试获取实例锁。
另请注意,使用原子字段可以在根本不同步的情况下解决此特定任务:
Static and instance
synchronized
methods are not related to each other, therefore you need to apply some additional synchronization between them, like this:(though in this case leaving
synchronized
onget()
doesn't make sense, since it doesn't do anything that requires synchronization on instance).Beware of deadlocks - since this code aquires multiple locks, it should do it in consistent order, i.e. other synchronized static methods shouldn't try to acquire instance locks.
Also note that this particular task can be solved without synchronization at all, using atomic fields:
同步静态方法实际上相当于:
换句话说,它锁定与声明该方法的类关联的 Class 对象。
来自 JLS 的第 8.4.3.6 节:
A synchronized static method is effectively equivalent to:
In other words, it locks on the
Class
object associated with the class declaring the method.From section 8.4.3.6 of the JLS:
如果您阅读 http://download.oracle.com/javase/tutorial/ Essential/concurrency/locksync.html。
它会告诉你:
它告诉你所有你需要知道的。
If you read http://download.oracle.com/javase/tutorial/essential/concurrency/locksync.html.
It will tell you:
which tells you all you need to know.
非静态同步调用也不会获取类本身的锁。 (静态同步块不会锁定从该类实例化的任何对象。)
换句话说,调用
f.get()
(锁定f
)和Foo .inc()
(锁定类Foo
)可以并发运行。它们不是“同步的”。您可以使用不同的模式(单例),或将所有方法设为静态。
Neither, the non-static synchronized call does not acquire a lock on the class itself. (And the static synchronized block does not lock any object instantiated from that class.)
In other words the calls
f.get()
(locksf
) andFoo.inc()
(locks the classFoo
) can run concurrently. They are not "synchronized".You could use a different pattern (singleton), or make all the methods static.
静态
锁附加到class
定义,因此在该类的所有实例之间共享。非静态
方法的同步仅适用于类的当前实例(锁位于类实例上,例如this
)。在您的示例中,您有两个没有相互关系的不同锁。您必须共享一个锁才能仲裁对
f.get
和Foo的访问.inc()。您可以通过共享相同的静态锁或相同的实例锁来完成此操作。
Static
locks are attached to theclass
definition and thus is shared between all instances of that class.Synchronization of
none static
methods only apply to the current instance of the class (the lock is on the class instance, e.g.,this
). In your example you have two different locks with no interrelation.You must share a lock to be able to arbitrate access to both
f.get
andFoo.inc()
. You can do this either by sharing the same static lock or by the same instance lock.这两个调用彼此不同步。
正如你所说,
f.get()
的调用者获取f
对象的锁,而Foo.inc()
的调用者获取Foo.class
对象就是其中之一。因此,同步规则与使用另一个对象调用实例同步方法而不是静态调用相同。These two calls do not synchronize in respect to each other.
It is as you said, a caller of
f.get()
acquires the lock off
object and caller ofFoo.inc()
acquiresFoo.class
object's one. So the synchronization rules are the same as if instead of static call you called an instance synchronized method with another object.