为什么将虚拟对象作为块级同步的参数传递?
在 Spring 源代码中找到了这段代码。这是将 XML 文件转换为 Bean Tree 的第一步。
/** Synchronization monitor for the "refresh" and "destroy" */
private final Object startupShutdownMonitor = new Object();
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
}
Found this code in the Spring source. This is the first step where the XML file is converted to Bean Tree.
/** Synchronization monitor for the "refresh" and "destroy" */
private final Object startupShutdownMonitor = new Object();
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
该习惯用法用于更精细的级别同步。以下是 Java 教程 的摘录。您可以使用
synchronized(this)
,但它会锁定整个对象。从 Java 5 开始,java 引入了
Lock
抽象提供更多功能。因此,您可以执行如下操作,而不是使用synchronized(obj)。了解更多详细信息This idiom is used for finer level synchronization. Here is the excerpt from the Java tutorial. You could have used
synchronized(this)
but that whould have locked on the entire object.Starting Java 5, java introduced
Lock
abstraction providing more functionality. So, instead of synchronized(obj) you can do something like below. Read more details here我不能具体代表 Spring 作者,但总的来说......
这样做是为了使代码同步(显然),但故意不在
this
上同步。我们为什么要这样做?有几个原因:
synchronized(theObject)
并最终在类外部使用与您在类内部使用的相同对象作为锁。在某些情况下,这可能会导致严重的性能/并发问题为什么要使用
对象
?因为这就是获得锁所需要的一切,其他任何东西都会带来更多的开销。I can't speak for the Spring authors specifically, but in general...
This is done so that the code is synchronized (obviously) but intentionally not synchronized on
this
.Why would we want to do this? There are a couple of reasons
synchronized(theObject)
and end up using the same object as a lock outside your class as you used inside your class. In some cases this could cause serious performance/concurrency issuesWhy an
Object
? Because that's all that's needed in order to get a lock, and anything else would introduce more overhead.我假设您从根本上想知道为什么他们不使用
synchronized(this)
?您发布的代码可能更好的原因大致有两个。this
上同步时,几乎肯定是在另一个类的监视器上同步)。您可以编写代码,使其独立工作,但如果其他代码使用它以特定方式同步,则会产生死锁。在this
上同步实际上是公开的,但我怀疑您通常会记录它(或者其他开发人员会阅读该文档)。通过在这样的私有最终字段上进行同步,您可以保证没有其他代码可以在同一对象上进行同步,从而极大地简化了您需要保护的逻辑。this< 上同步/code>,那么这些方法中只能同时发生其中一种。通过对特定对象进行同步,您可以创建组内互斥的方法/块组,但不会阻止其他组中的块继续进行。
第一个可以说是最重要的,因为它可能会设置一个非常难以调试的定时炸弹。第二个也是相关的 - 开发人员经常在没有意识到的情况下过度限制独立的操作 - 但仅适用于同一类中确实有多个操作组的情况。
如今,如果我要同步,我总是会在特定的
new Object()
字段上进行同步,即使目前只是一个操作。I assume that fundamentally you're wondering why they didn't use
synchronized(this)
? There are broadly two reasons why the code you've posted might be better.this
you're almost certainly synchronizing on the monitor of another class). You could write your code such that it works standalone, but creates deadlocks if some other code using it, synchronizes in a particular way. Synchronizing onthis
is effectively public, but I doubt you'd typically document it (or that another developer would read that documentation). By synchronizing on a private final field like this, you can guarantee that no other code can synchronize on the same object, massiovely simplifying the logic of what you need to protect.this
, then only one of those methods can ever occur at once. Synchronizing on specific objects lets you create groups of methods/blocks that are mutually exclusive within the group, but don't prevent blocks from another group from proceeding.The first is arguably the most important, as it can set up a ticking time bomb that can be very difficult to debug. The second is also relevant - and developers often over-constraint independent operations like that without realising - but only applies when you do have multiple groups of operations within the same class.
Nowadays if I'm synchronizing, I'll always do it on a specific
new Object()
field, even if it's just a single operation for the moment.啊,我以前见过这个:)我实际上也思考过同样的事情。
如果我没记错的话,这是来自 AbstractApplicationContext 。
将一个方法标记为同步意味着没有 2 个线程可以同时调用该方法或任何其他同步方法(锁位于类上)。
拥有一个监视器对象并在同步块中使用它具有相同的效果,但对于使用相同虚拟对象的同步块中的所有代码而言。
如果我没记错的话,在同一个类中还有另一个监视器,称为 activeMonitor。
这允许更高的并发性(线程同时访问两个对象同步的方法)。
这可以让他安全地避免将他的监视器(他的班级之外的任何人都没有兴趣)泄露给其他可能滥用它的对象(将其置于永久权限状态),从而在这个过程中弄乱他的监视器。
Ah I've seen this before :) I've actually pondered the same thing.
This is from AbstractApplicationContext if I remember correctly.
Marking a method as synchronized means that no 2 threads can be calling this method or any other synchronized method at the same time (the lock is on class).
Having a monitor object and using it in a synchronized block like this has the same effect but for all code in synchronized blocks that use the same dummy object.
If I remember correctly as well there is another monitor in this very same class called activeMonitor.
this allows for higher concurrency (threads accessing methods synchronized by both objects at the same time).
this allows keeps him safe from leaking his monitor (which is of no interest to anyone outside his class) out to other objects that might abuse it (place it in a state of eternal dibs), thus messing with his in the process.
如果一段代码具有某些类变量,并且彼此完全独立,那么与其使用
synchronize(this)
获取整个对象的锁,不如对虚拟对象使用锁。里面的代码仍然受到保护,因为监视器现在处于虚拟对象锁定状态。If a piece of code having certain class variables is completely independent from the other, then instead of acquiring a lock on the entire object by using
synchronize(this)
it is better to use lock on dummy object. The code inside is still protected because the monitor now lies with dummy object lock.这相当于以下内容:
获取实例对象
startupShutdownMonitor
的锁与获取调用刷新方法的类的实例的锁相同。This is equivalent to the following
Acquiring a lock on the instance object
startupShutdownMonitor
is same as acquiring a lock on the instance of the class on which refresh method is being called upon.