Win a copy of Java Concurrency Live Lessons this week in the Threads forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Java Synchronization code  RSS feed

 
ken carlino
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Is there any difference between these 2 pieces of code?

class A {
private Object lock = new Object();

public void aMethod() {
synchronized (lock) {
// some code here
}
}
};
and this one:

class A {
public void aMethod() {
synchronized(this) {
// some code here
}
}

Thank you.
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
They are nearly identical in effect - however the first version has the advantage that because "lock" is private, there's no danger that any code outside of this class will try to synchronize on it, which could otherwise cause deadlock. Typically there would be no reason for code outside this class would try to synchronize on it, but you never know when someone might try something crazy and unpredictable with the code. Deadlock can be a particularly frustrating problem to deal with, so it may be worthwhile to provide a little extra protection against the possibility that any "unauthorized" code might try to sync on your lock object.

Note also that in JDK 5.0, the java.util.concurrent.locks package has several Lock implementations which you would use in a somewhat similar fashion to this. Java programmers are often used to implicitly synchronizing on "this", but that's not the only way to perform locking. I would argue that it's easier for people to understand and remember the purpose of a lock, if it's a separate feature from the class which contains it. Implicitly synchonizing on "this" is often a bit too tranparent - beginners may not even realize what's happened, or what the monitor object is. So I like the idea of explicitly synchronizing on an object which is distinct from the usual "this". Unfortunately it's not a very common practice in Java, in my experience.
 
Purushoth Thambu
Ranch Hand
Posts: 425
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

there's no danger that any code outside of this class will try to synchronize on it, which could otherwise cause deadlock


I believe deadlock is possible only with 2 or more synchronized objects and 2 or more threads. Even with synchronized private object its possible to have a dead lock [if the synchronized block access another synchronized object]. For me the code snippet doesn't look any different expect that the first part consumes additional memory for Object.
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
[PT]: I believe deadlock is possible only with 2 or more synchronized objects and 2 or more threads.

Yes. If there weren't two or more threads (or at least the possibility there are), we wouldn't be worrying about synchronization at all, would we? And yeah, the code shown so far doesn't show other objects or code which might create deadlock. But you do have "// some code here" and I don't know what will go there. It could be something that would create deadlock. And even if, at the time you write the code, you have analyzed carefully and determined that there's no possibility of deadlock - there's still a chance that someone later on will innocently add something that has unanticipated consequences. Of course you can't ever fully guard against the possibility that someone in the future will introduce bad code. But you can take some steps to minimize the possibility of it occuring. Using a private lock is a fairly simple technique which makes it harder for any "unauthorized" code to sync on your lock - which in turn makes it less likely someone will be able to introduce a bug which creates deadlock. It doesn't prevent the possibility of deadlock, but it reduces the possibility of it.

Also, using a hidden lock has additional benefits if you're using a wait/notify system. When you wake up after a wait(), it's nice to know exactly who notified you, and why. But if you're waiting and notifying using a publicly-accessible monitor (e.g. "this" in many cases) then you often don't really know what other code might decide to send a notify using the same monitor. It's fairly rare that this is an issue, but it can be very confusing to diagnose if the issue does arise. So again, using a private monitor you can carefully control what code is using that monitor for something.
 
Mr. C Lamont Gilbert
Ranch Hand
Posts: 1170
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thats right Jim. Probably has a lot to do with the recommendation that you recheck your conditions after a notify(), when in actuality you shouldn't have to. But since folks expose their monitors all over the place one can't really be sure where the notify came from. Now that I think about it, if you are using notify and not notifyall you have yet another problem. Another object can intercept your notify and neglect to pass it on to the other potential waiters.

Personally I always hide my monitors. Sun is guilty of exposing them everywhere. Once you expose it, it becomes part of your contract. People will not be happy if you change it since they must re-validate their whole application.
 
Purushoth Thambu
Ranch Hand
Posts: 425
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

If there weren't two or more threads (or at least the possibility there are), we wouldn't be worrying about synchronization at all,



Jim, Synchronization is not about dead lock. Dead lock in fact is side effect of synchronization. You synchronize to serialize access to the object. Synchronization is all about ACID. I still can't see how synchronizing on a private object will avoid/reduce deadlock or is better than synchronizing on this. All the issue you say can very well happen with synchronized private object as well. Moreover if synchronizing on private object is beneficial I believe Sun would have actually implemented it. Is there any URL/link that demonstrates this case? May be I missed all these..
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
[PT]: Jim, Synchronization is not about dead lock. Dead lock in fact is side effect of synchronization.

Well it's obviously not an intended goal. But I think it's something to consider and to avoid if possible.

[PT]: I still can't see how synchronizing on a private object will avoid/reduce deadlock or is better than synchronizing on this. All the issue you say can very well happen with synchronized private object as well.

I've already agreed that they can happen. I contend that they are less likely to happen. Other code can still acquire the lock, simply by calling your method which uses the lock. But if they do that, your code is in control of what other code gets called while the lock is held. Depending what you choose to do, you can still create deadlock or other errors. But at least that control is yours; you don't have to cede that control to outside code.

[PT]: Moreover if synchronizing on private object is beneficial I believe Sun would have actually implemented it.

You mean they way they have in the java.util.concurren.locks package? OK, that's not actually synchronization; it's a more flexible alternative to synchronization. As for standard synchronization: do you really believe Sun got everything just right when they designed Java? The fact that something is part of Java should not be taken as evidence it's perfect. There have been plans to bring in the java.util.concurrent stuff for some time (based off Doug Lea's util.concurrent stuff), but it was partly contingent on revisions to the memory model which were only completed in JDK 5.

I should note that there are also some times when a public monitor is necessary. For example, consider iterating through a synchronizedList(). Individual methods in a synchronizedList() are synchronized - but iterating requires you to call two different methods, repeatedly. The only way to do that (without changing the API entirely) is by using a public monitor and documenting the fact that clients are expected to use it - as is explained in the API for Collections.synchronizedList(). I generally dislike such techniques, as in many cases the programmers of client code haven't carefully read the docs, and don't understand the precise requirements. Whenever possible, I prefer to limit the possibility that clients can misuse my classes, and cotrol all synchronization internally.

[PT]: Is there any URL/link that demonstrates this case? May be I missed all these..

Let's see... there's Effective Java by Joshua Bloch, p. 210. That's more about defending against malicious code than from accidental deadlock, but the idea is similar enough. A nice discussion can be found online here. Ultimately I think this is a fairly minor topic as there are usually far more serious concerns to learn about when multithreading is involved, so it doesn't get much coverage. Or perhaps there's more out there, but most of the search terms I can think of aren't terribly distinctive from general threading discussions.
[ June 08, 2006: Message edited by: Jim Yingst ]
 
Purushoth Thambu
Ranch Hand
Posts: 425
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks, The link did really help me to understand private and public monitors...
 
Consider Paul's rocket mass heater.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!