views:

436

answers:

3

Now, I'm not sure whether this is a stupid question, please bear with me if it is.

Is the lock on an object "recursive", i. e. if two objects have references to a third object in their fields and a thread is running a synchronized method on one of the two, can any other thread access the third object?

// a and b are some objects that implement Runnable
// they both reference the same third object
a.ref = c;
b.ref = c;

// a is run in a thread and processes some data in a loop for a long time
// the method the loop belongs to is declared synchronized
threadA = new Thread(a);
threadA.start();

a.someSyncedMethod(); // this would block ...
b.ref.someOtherSyncedMethod(); // ... but would this?
a.ref.someOtherSyncedMethod(); // ... and how about this?
+7  A: 

It's worth separating out the concepts of "a lock" and "locking an object". There's no real idea of "locking an object" - there's "acquiring (and releasing)" the lock associated with an object. Yes, it sounds like I'm nitpicking - but the distinction is important because if you talk about an object being locked it sounds like no other threads will be able to change anything in the object while that lock is held.

Instead, it just means that no other thread will be able to acquire the same lock while the lock is held. There's no direct relationship between the lock and any of the contents of the object that the lock is associated with.

Methods declared "synchronized" acquire the lock associated with the instance of the object they belong to. This only makes other synchronized methods on the same object wait, and synchronized statements that explicitly sync on it.

Personally I don't like synchronized methods - I like to make it clearer by explicitly synchronizing on a (private, final) member variable which is only used for synchronization.

Jon Skeet
Yeah, it does help, but I'm not sure if I've really got it. Is it correct that only those calls will block that need the same lock, i. e. calls to synchronized methods of the same instance, while any code that locks on a member of a will proceed?
Hanno Fietz
Yes. Personally I don't like synchronized methods - I like to make it clearer by explicitly synchronizing on a (private, final) member variable which is only used for synchronization.
Jon Skeet
I edited the above into your post, I hope, I got it right. Thanks!
Hanno Fietz
I've changed "a" to "the" but otherwise fine and great, thanks :)
Jon Skeet
+1  A: 
a.someSyncedMethod(); // this would block ...

Only if you mark either the run method with synchronized or have ThreadA run code in synchronized methods.

In the JVM, each object owns what's known as a monitor. Only one thread can own the monitor associated with a given object at a time. Synchronized is the means by which you tell the current thread to go get the monitor before continuing.

Also the class itself owns a monitor for static methods.

Martin OConnor
A: 

The meaning of a "lock" (actually this variant is called a monitor) is entirely a convention, no access restrictions are enforced.

The functioning relies on all objects being well-behaved and acquiring the corresponding lock before accessing the data. Only by encapsulating this desired behaviour within in a class with proper access controls you can enforce it for the client objects.

starblue