Question on synchronized and non synchronized methods


A

ankur

Hello all,

Is it correct to say that a thread can execute a non synchronized
method on a shared object on which another thread is already executing
a synchronized method ?

If the above is true then is it true that for a shared object it would
be wise to have all methods declared synchronized, esp if the
operations in those methods if performed in an interleaved fashion can
result in an inconsistent state of the object ?
 
Ad

Advertisements

A

ankur

Yes.  Assuming no other synchronization is done, of course (the  
"synchronized" keyword isn't the only way to synchronize threads).


For operations that need to be synchronized (for example, those which  
would otherwise "result in an inconsistent state"), you definitely should  
synchronize them if you expect your code to be thread-safe.  No "would be  
wise" about it...your program simply can't be considered thread-safe  
otherwise.

Note though that synchronization comes at a cost, and so you should only  
add synchronization to objects that need to be thread-safe, or in those  
methods that need to be thread-safe.  Sometimes this is every single  
public method, sometimes it's just specific operations.

Other approaches to thread-safety include making an object immutable  
(rather than having methods modify the called-on object, return a new  
instance of the object with those modifications), or simply _using_ the  
object in a thread-safe way (i.e. have the caller worry about  
synchronization, rather than building synchronization into the object  
itself).

Of course, multi-threaded code is hard enough as it is.  Obviously you  
should do the simplest thing first, and if that means synchronizing every  
single method, so be it.  Slow, correct code is far better than fast,  
incorrect code.  :)

Pete

Thanks Pete !
 
M

Mike Schilling

ankur said:
Hello all,

Is it correct to say that a thread can execute a non synchronized
method on a shared object on which another thread is already
executing
a synchronized method ?
Yes.


If the above is true then is it true that for a shared object it
would
be wise to have all methods declared synchronized, esp if the
operations in those methods if performed in an interleaved fashion
can
result in an inconsistent state of the object ?

If an object will be accessed from multiple threads, any methods that
either

1. Change the object's state, or
2. Access state that might be changed by a method described by 1

should be synchronized. There are advanced optimization techniques
that allow breaking these rules, but stick with them unless you're
sure both that you have a good reason to break them and you're 100%
convinced that it's safe to do so. [a]

Note, by the way, that one of the great advantages of immutable
objects is that you don't have to synchronize them, because their
state doesn't change.

a. For the sake of being less mysterious, I'll give an example.
Consider the hashCode for a String object. It can be fairly expensive
to calculate, since that requires processing all of its characters,
thus it makes sense to calculate it lazily, e.g.

private int code;
public int hashCode()
{
if (code == 0)
code = calculateHashCode();
return code;
}

Since this method potentially changes the String's state, strictly
speaking it should be synchronized. But let's think about what
happens if it isn't. Given that the assignment to "code" is atomic,
the worst thing that can happen if two threads call "hashCode()" at
the same time is that they both calculate the hash code, and the
second one to complete overwrites "code" with the same value that the
other one did. Thus it's allowable, in this case, to leave it
unsynchronized. Since Strings are often used as hash keys, that might
be a useful optimization.

But to come to this conclusion, we had to look pretty deeply into the
situation. Using the rules above and marking it synchronized is much
simpler and guaranteed to be correct.
 
M

Mark Space

ankur said:
Hello all,

Is it correct to say that a thread can execute a non synchronized
method on a shared object on which another thread is already executing
a synchronized method ?

If the above is true then is it true that for a shared object it would
be wise to have all methods declared synchronized, esp if the
operations in those methods if performed in an interleaved fashion can
result in an inconsistent state of the object ?


No, it's not wise. The big problem with adding "synchronized" to every
method is deadlock. If you have lots of objects, all taking locks, I
think invariably you'll get into a situation where two threads are
holding locks the other needs. I can't imagine trying to work with a
system where every method was synchronized. The lock ordering needed to
make this work would be horrendous.

I think Peter's answer to use non-synchronized objects in a thread safe
way is the best. Design all your leaf and value classes as not thread
safe. Isolate the GUI and the EDT from the rest of the program. Then
from a higher level, design threads of execution through the program as
tasks which implement their own thread safe behavior. You may have to
go back and muck with your lower level classes a bit, but I think you'll
have a much clearer idea what needs to be done at that point, and the
design will be much better for it.
 
Ad

Advertisements

E

Eric Sosman

ankur said:
Hello all,

Is it correct to say that a thread can execute a non synchronized
method on a shared object on which another thread is already executing
a synchronized method ?

Yes. An object's monitor ("lock") can be held by at most
one thread at a time, and the *only* thing `synchronized' does
is to acquire the lock, stalling if necessary until the lock is
available, and then release it when the synchronized block exits.
A method that does not attempt to acquire the lock will not be
impeded if some some other thread happens to hold it, nor will
it prevent another thread from acquiring it.
If the above is true then is it true that for a shared object it would
be wise to have all methods declared synchronized, esp if the
operations in those methods if performed in an interleaved fashion can
result in an inconsistent state of the object ?

It is not true that *all* methods must be synchronized.
For example, consider a Person object that has some mutable
and some immutable fields. Methods that observe or change
the mutable fields must be synchronized, but a method that
observes only the immutable fields doesn't need to be:

class Employee {
private final String name;
private Employee manager;

Employee(String name, Employee manager) {
this.name = name;
this.manager = manager;
}

String getName() {
return name;
}

synchronized void assignToManager(Employee manager) {
this.manager = manager;
}

synchronized Employee getManager() {
return manager;
}
}

The getName() method requires no synchronization because the
employee's name never changes (in this too-simplistic example).
Both the assignToManager() and getManager() methods synchronize,
because they manipulate and observe mutable state of the Employee
object.

(In some circumstances it's possible to use `volatile' to
avoid the need for synchronization, but it's *very* easy to use
`volatile' incorrectly; I'd suggest you ignore it until your
understanding of synchronization is secure.)
 

Top