In what cases is it necessary to synchronize access to instance members? I understand that access to static members of a class always needs to be synchronized- because they are shared across all object instances of the class.
My question is when would I be incorrect if I do not synchronize instance members?
for example if my class is
public class MyClass {
private int instanceVar = 0;
public setInstanceVar()
{
instanceVar++;
}
public getInstanceVar()
{
return instanceVar;
}
}
in what cases (of usage of the class MyClass
) would I need to have methods:
public synchronized setInstanceVar()
and
public synchronized getInstanceVar()
?
Thanks in advance for your answers.
Synchronization is needed when Object is mutable. If shared Object is immutable or all the threads which share the same Object are only reading the Object's state not modifying then you don't need to synchronize it. Java programming language provide two synchronization idioms: Methods synchronization.
Synchronized methods enable a simple strategy for preventing thread interference and memory consistency errors: if an object is visible to more than one thread, all reads or writes to that object's variables are done through synchronized methods.
Synchronized method is used to lock an object for any shared resource. When a thread invokes a synchronized method, it automatically acquires the lock for that object and releases it when the thread completes its task.
synchronized block has better performance as only the critical section is locked but synchronized method has poor performance than block. synchronized block provide granular control over lock but synchronized method lock either on current object represented by this or class level lock.
The synchronized
modifier is really a bad idea and should be avoided at all costs. I think it is commendable that Sun tried to make locking a little easier to acheive, but synchronized
just causes more trouble than it is worth.
The issue is that a synchronized
method is actually just syntax sugar for getting the lock on this
and holding it for the duration of the method. Thus, public synchronized void setInstanceVar()
would be equivalent to something like this:
public void setInstanceVar() {
synchronized(this) {
instanceVar++;
}
}
This is bad for two reasons:
synchronized
methods within the same class use the exact same lock, which reduces throughputThere is nothing to prevent me from doing something like this in another class:
MyClass c = new MyClass();
synchronized(c) {
...
}
Within that synchronized
block, I am holding the lock which is required by all synchronized
methods within MyClass
. This further reduces throughput and dramatically increases the chances of a deadlock.
A better approach is to have a dedicated lock
object and to use the synchronized(...)
block directly:
public class MyClass {
private int instanceVar;
private final Object lock = new Object(); // must be final!
public void setInstanceVar() {
synchronized(lock) {
instanceVar++;
}
}
}
Alternatively, you can use the java.util.concurrent.Lock
interface and the java.util.concurrent.locks.ReentrantLock
implementation to achieve basically the same result (in fact, it is the same on Java 6).
It depends on whether you want your class to be thread-safe. Most classes shouldn't be thread-safe (for simplicity) in which case you don't need synchronization. If you need it to be thread-safe, you should synchronize access or make the variable volatile. (It avoids other threads getting "stale" data.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With