可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I was wondering if in Java I would get any odd behaviour if I synchronise twice on the same object?
The scenario is as follows
pulbic class SillyClassName {
object moo;
...
public void method1(){
synchronized(moo)
{
....
method2();
....
}
}
public void method2(){
synchronized(moo)
{
doStuff();
}
}
}
Both methods use the object and are synchronised on it. Will the second method when called by the first method stop because it's locked?
I don't think so because it's the same thread but I'm unsure of any other odd results that might occur.
回答1:
Reentrant
Synchronized blocks use reentrant locks, which means if the thread already holds the lock, it can re-aquire it without problems. Therefore your code will work as you expect.
See the bottom of the Java Tutorial page Intrinsic Locks and Synchronization.
To quote as of 2015-01…
Reentrant Synchronization
Recall that a thread cannot acquire a lock owned by another thread. But a thread can acquire a lock that it already owns. Allowing a thread to acquire the same lock more than once enables reentrant synchronization. This describes a situation where synchronized code, directly or indirectly, invokes a method that also contains synchronized code, and both sets of code use the same lock. Without reentrant synchronization, synchronized code would have to take many additional precautions to avoid having a thread cause itself to block.
回答2:
I think we have to use reentrant lock for what you are trying to do. Here's a snippet from http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/ReentrantLock.html.
What do we mean by a reentrant lock? Simply that there is an acquisition count associated with the lock, and if a thread that holds the lock acquires it again, the acquisition count is incremented and the lock then needs to be released twice to truly release the lock. This parallels the semantics of synchronized; if a thread enters a synchronized block protected by a monitor that the thread already owns, the thread will be allowed to proceed, and the lock will not be released when the thread exits the second (or subsequent) synchronized block, but only will be released when it exits the first synchronized block it entered protected by that monitor.
Though I have not tried it, I guess if you want to do what you have above, you have to use a re-entrant lock.
回答3:
Java appears to fully support nested locks on one object by the same thread. This means that if a thread has an outer and an inner lock on an object, and another thread tries to lock on the same object, the second thread will be suspended until both locks have been released by the first thread.
My testing was done under Java 6 SE.
回答4:
No problems. In your example, (once you fix your code to get rid of the compile warnings that you'll get ;) ), the synchronization ensures that the blocks in method1 and method2 will not execute simultaneously.
That's kind of the point of synchronization. :)
Edit: Sorry, missed parts of your question, but Phill answered it. To summarize, a single thread cannot deadlock itself.
回答5:
In java, the synchronized
keyword on a method basically synchronizes on the current object, so in effect it's doing what you suggest above implicitly.
You won't experience problems with synchronizing on one object in one method and then synchronizing on the same object in another method because, as you say, the current thread already holds the lock on that object.
回答6:
No, the second method will not stop if called by first. No odd results will occur (except a slight overhead for checking lock. This wont matter much. Java 6 onwards, you have lock coarsening in the JVM - http://java.sun.com/performance/reference/whitepapers/6_performance.html )
For example, take a look at source code of java.util.Vector. There are lot of calls to other synchronized methods from within synchronized methods.