Multiple object locks in Java? - java

Is it safe/acceptable practice to lock on a private field variable (instead of using a lock object)? This way, I could have different locks for different purposes. Example below:
class Test {
private Integer x = 0;
private Integer y = 0;
public void incrementX() {
synchronized(x) {
x++;
}
}
public void decrementX() {
synchronized(x) {
x++;
}
}
public void incrementY() {
synchronized(y) {
y++;
}
}
public void decrementY() {
synchronized(y) {
y++;
}
}
Or should I have a lock object for each private member I wish to lock? Example:
class Test {
private final Object xLock = new Object();
private final Object yLock = new Object();
private Integer x = 0;
private Integer y = 0;
...
}
Or should I just have a single general lock and use that for all private variables that require locking? Example:
class Test {
private final Object objLock = new Object();
private Integer x = 0;
private Integer y = 0;
...
}

Beware to always use a final member var for the lock! If you use an Integer, for example, and you plan to change it, that will be very bad practice since each call will see a different object and cause a data race.
Whether you use one or several locks depends on the coordination scheme you want to achieve, so it's entirely domain-specific. You must think through carefully which operations are and which aren't mutually exclusive and assign locks to them appropriately. There is no single best practice here.
If you have two orthogonal operations on your object that may happen simultaneously without causing any datarace, that's a case for two locks. In your example there are two Integers, each changing independently. I see this as a case for two locks. If you had more complex code where in at least one operation you needed to access both Integers, that would tie them together and then you would need a single lock.

It's perfectly acceptable to lock on a private field, as long as this field is an object. Primitives don't have an intrinsic lock, and the first snippet is thus invalid.
I would however avoid locking on a private field if this field is accessible from the outside (using a getter, for example), as this would allow anyone to lock on the same object for different purposes. The second solution is thus the cleanest, IMHO.
Using a single lock is counter-productive, since it prevents concurrent access to methods which should be able to run concurrently. It's thus generally better to have fine-grained the locks.
EDIT:
now that you have changed your question and use wrapper objects, the locking on the private Integer instances is really not a good solution, as you change the values of these variables inside the methods. Use final fields as locks.
Remember that x++, if x is an Integer instance, is equivalent to:
int temp = x.intValue();
temp++;
x = Integer.valueOf(temp);
Moreover, since Integer.valueOf() caches Integer instances, you might have several classes using the same Integer instance to lock completely different things. A recipe for slow execution and deadlocks.

I think you should have two different lock for the two fields. You lock the object to prevent two or more thread access the same object at the same time.
You can also take a look to the Lock object in java http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/Lock.html
It is more performant than the synchronize, and in the java.util.concurrent there are some utility class to work with locks (also a ReadWriteLock, if you need it)

AFAIK the lock object you use is only as an ID. I mean, you can use whatever object you want. The only important thing is "if two things must be mutually exclusive, then they must use the same lock".
So the approach of using the very own var seems ok.
BUT, remember!!
I don't think you can lock on a primitive, it must be an Object
If you change the field value, next process will acquire a different lock!!!
So the separate lock seems safer. Except you are absolutely sure your field is not going to change (in fact, you should declare it as final).

Related

Is field's default value guaranteed to be visible among threads?

Discussing this answer I was wondered why didn't we use sychronization when assigning default values.
class StateHolder {
private int counter = 100;
private boolean isActive = false;
public synchronized void resetCounter() {
counter = 0;
isActive = true;
}
public synchronized void printStateWithLock() {
System.out.println("Counter : " + counter);
System.out.println("IsActive : " + isActive);
}
public void printStateWithNoLock() {
System.out.println("Counter : " + counter);
System.out.println("IsActive : " + isActive);
}
}
This class looks thread safe because access to its fields is managed by a synchronized method. That way, all we have to do is to publish it safely. For instance:
public final StateHolder stateHolder = new StateHolder();
Can it be considered as a safe publication? I think no, it cannot. Consulting the final field semantic (emphasized mine) I figured out that the only thing guarnteeed is that stateHolder reference is not a stale one. :
A thread that can only see a reference to an object after that object
has been completely initialized is guaranteed to see the correctly
initialized values for that object's final fields.
final field semantic is not concerned about the state of the ojbect referenced to by the final field. That way, another thread might as well see default values of the fields.
QUESTION: How can we guarantee memory consistency of the filed's values assigned within a constructor or instance initializer?
I think we have to declare them either volatile or final as that there is no happens-before relationship bethween assigning a reference and constructor invocation. But lots of library classes does not declare fields that way. java.lang.String is an example:
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence{
//...
private int hash; //neither final nor volatile
//...
}
final can guarantee you that you'll see the assigned value to an instance variable after the instance construction without the need of any further action. You just need to make sure that you don't leak the constructed instance within the constructor.
volatile can also guarantee you that you'll see the default value that you set for some instance variable, because the instance variable initializers are guaranteed to be executed before the end of the constructor per JLS 12.5 Creation of New Class Instances.
Safe publication is not entirely trivial, but if you stick with one of the popular mechanisms for achieving it, you should be perfectly fine. You can take a look at Safe Publication and Safe Initialization in Java for some more interesting details.
As for String.hash, it's a popular example of the so-called benign data races. The accesses to the hash instance variable allow both racing of a read and write and racing of two writes. To illustrate just the latter, two threads can simultaneously:
see the initial value of 0
decide that they are the first to calculate the hash
calculate the hash code and write to the same variable without any synchronization
The race was still allowed and considered to be benign because of two reasons:
Hash code calculation for the immutable String instances is an idempotent operation.
Writes of 32-bit values are guaranteed not to tear.
Even benign data races are still not recommended though. See Benign data races: what could possibly go wrong? or Nondeterminism is unavoidable, but data races are pure evil.

Atomically update multiple volatile and j.u.c.atomic variables

In order to atomically update two and more volatile variables does it need to be guarded by lock with synchronized, reentrantReadWriteLock etc?
i.e.
volatile int vVar1, vVar1; // or AtomicInteger
/*** Needs to be updated atomically ***/
void atomicUpdate(int var1, int var2){
vVar1 = var1;
vVar2 = var2;
}
The same code is for java.util.concurrent.atomic variables.
If you need to assign two values atomically, chaning volatile int to AtomicInteger will not solve your race condition problem.
To solve your issue, you basically have two options:
Make the methods updating the variables synchronized (and maybe the methods reading those variables too)
Create an wrapper for your two variables, and make use of the fact that assignment is an atomic operation
Example for option 2:
volatile Vars vars;
void atomicUpdate(int var1, int var2) {
vars = new Vars(var1, var2);
}
public static Vars {
private int vVar1; // volatile if they need to be modified
private int vVar2;
}
I largely prefer option 2 since it is non blocking and allows you to cache any type of data.
Create a Class which encapsulates all of your state variables, then use AtomicReference to refer to them. This alleviates race conditions where a thread needs to set/check multiple values safely.
// set initial state
AtomicReference<MyState> ref = new AtomicReference<MyState>();
ref.set(new MyState("abc", "def"));
// .. Thread 1 needs to change the state:
ref.set(new MyState("xyz", "def"));
// .. Thread 2 needs to read the state (consistently):
MyState state = ref.get();
if ("test1".equals(state.a)) { }
else if ("test2".equals(state.b) { }
The benefit here is that Thread 2 is able to read MyState.a and MyState.b consistently from the same MyState instance, as opposed to having the MyState instance variable it's referencing change in-between checks.
I want to update my two variables atomically
You can't. There are no atomic operations in the Java language or in the Java standard library that span more than one variable.
You can probably solve your problem using the synchronized keyword, but using synchronized is different from using atomics because, in order for it to work, the threads must cooperate with one another.
If there is a specific relationship that must always exist between those two variables (a.k.a., an invariant), and if you can't update the variables without temporarily breaking the invariant, then you must synchronize the code that does the update, and you must also synchronize every other block of code that expects the invariant to be true.
That's because, when you write this:
synchronized(foo) { ... }
It doesn't prevent other threads from doing anything except synchronizing on the same object at the same time.
Also note: Once you have properly synchronized all access to the variables, then you won't need them to be volatile. That's because whatever one thread writes to memory before releasing a lock is guaranteed to become visible to any other thread that subsequently acquires the same lock.
An alternative would be to use a volatile array:
private volatile int[] var;
void update (int var1, int var2) {
var = new int[] { var1, var2 };
}
that would be atomic but it assumes that the rest of your code does not access vVar1 and vVar2 directly. There may be better options depending on what you are trying to achieve - for example you could create an ad hoc thread safe holder class (typically immutable) for the two ints.

Lazy initialization without synchronization or volatile keyword

The other day Howard Lewis Ship posted a blog entry called "Things I Learned at Hacker Bed and Breakfast", one of the bullet points is:
A Java instance field that is assigned exactly once via lazy
initialization does not have to be synchronized or volatile (as long
as you can accept race conditions across threads to assign to the
field); this is from Rich Hickey
On the face of it this seems at odds with the accepted wisdom about visibility of changes to memory across threads, and if this is covered in the Java Concurrency in Practice book or in the Java language spec then I have missed it. But this was something HLS got from Rich Hickey at an event where Brian Goetz was present, so it would seem there must be something to it. Could someone please explain the logic behind this statement?
This statement sounds a little bit cryptic. However, I guess HLS refers to the case when you lazily initialize an instance field and don't care if several threads performs this initialization more than once.
As an example, I can point to the hashCode() method of String class:
private int hashCode;
public int hashCode() {
int hash = hashCode;
if (hash == 0) {
if (count == 0) {
return 0;
}
final int end = count + offset;
final char[] chars = value;
for (int i = offset; i < end; ++i) {
hash = 31*hash + chars[i];
}
hashCode = hash;
}
return hash;
}
As you can see access to the hashCode field (which holds cached value of the computed String hash) is not synchronized and the field isn't declared as volatile. Any thread which calls hashCode() method will still receive the same value, though hashCode field may be written more than once by different threads.
This technique has limited usability. IMHO it's usable mostly for the cases like in the example: a cached primitive/immutable object which is computed from the others final/immutable fields, but its computation in the constructor is an overkill.
Hrm. As I read this it is technically incorrect but okay in practice with some caveats. Only final fields can safely be initialized once and accessed in multiple threads without synchronization.
Lazy initialized threads can suffer from synchronization issues in a number of ways. For example, you can have constructor race conditions where the reference of the class has been exported without the class itself being initialized fully.
I think it highly depends on whether or not you have a primitive field or an object. Primitive fields that can be initialized multiple times where you don't mind that multiple threads do the initialization would work fine. However HashMap style initialization in this manner may be problematic. Even long values on some architectures may store the different words in multiple operations so may export half of the value although I suspect that a long would never cross a memory page so therefore it would never happen.
I think it depends highly on whether or not an application has any memory barriers -- any synchronized blocks or access to volatile fields. The devil is certainly in the details here and the code that does the lazy initialization may work fine on one architecture with one set of code and not in a different thread model or with an application that synchronizes rarely.
Here's a good piece on final fields as a comparison:
http://www.javamex.com/tutorials/synchronization_final.shtml
As of Java 5, one particular use of the final keyword is a very important and often overlooked weapon in your concurrency armoury. Essentially, final can be used to make sure that when you construct an object, another thread accessing that object doesn't see that object in a partially-constructed state, as could otherwise happen. This is because when used as an attribute on the variables of an object, final has the following important characteristic as part of its definition:
Now, even if the field is marked final, if it is a class, you can modify the fields within the class. This is a different issue and you must still have synchronization for this.
This works fine under some conditions.
its okay to try and set the field more than once.
its okay if individual threads see different values.
Often when you create an object which is not changed e.g. loading a Properties from disk, having more than one copy for a short amount of time is not an issue.
private static Properties prop = null;
public static Properties getProperties() {
if (prop == null) {
prop = new Properties();
try {
prop.load(new FileReader("my.properties"));
} catch (IOException e) {
throw new AssertionError(e);
}
}
return prop;
}
In the short term this is less efficient than using locking, but in the long term it could be more efficient. (Although Properties has a lock of it own, but you get the idea ;)
IMHO, Its not a solution which works in all cases.
Perhaps the point is that you can use more relaxed memory consistency techniques in some cases.
I think the statement is untrue. Another thread can see a partially initialized object, so the reference can be visible to another thread even though the constructor hasn't finished running. This is covered in Java Concurrency in Practice, section 3.5.1:
public class Holder {
private int n;
public Holder (int n ) { this.n = n; }
public void assertSanity() {
if (n != n)
throw new AssertionError("This statement is false.");
}
}
This class isn't thread-safe.
If the visible object is immutable, then I you are OK, because of the semantics of final fields means you won't see them until its constructor has finished running (section 3.5.2).

Is there reasoning behind choosing a specific object?

Is the locking object used for synchronization arbitrary or is there reasoning behind choosing a specific object?
Why would you lock an object? Because it is shared among various threads. That's all there is. How you implement locking and threading is probably the difficult part, as opposed to choosing which object to lock on.
You'd be better off using one of the more modern locking techniques where much of the complexity and pitfalls have been removed/smoothed over. Package java.util.concurrent.locks would be a good start.
Your question is rather unclear.
You may be referring to a Semaphore object as a lock. You may also be referring to synchronized objects.
1) A semaphore may as well arbitrary object. It's intended purpose is that it can be used to hold threads at the semaphore until other threads release it.
2) Synchronized objects make all of their functions atomic: If a thread is operating on the object, the other object waits to complete its own function. This is usually implemented using a semaphore internally.
Semaphores are the objects used to solve synchronization problems.
The locking object needs to represent the exclusive part.
if you lock the whole object meaning using it exclusively by an thread, you may use the object "this" to lock. This is the way "synchronize" work on methods work.
public class A
{
public synchronized void do1 ()
{
...
}
public synchronized void do2 ()
{
...
}
}
if your object just has some set of members which should be used exclusively, you need separate (explicit) locking objects
public class B
{
private X x;
private Y y;
private Object lockXY = new Object ();
private R r;
private S s;
private Object lockRS = new Object ();
public void do1 ()
{
synchronize (lockXY) {
}
...
}
public void do2 ()
{
synchronize (lockRS) {
}
}
}
Beware to make locking to complex, you may run into dead locks
As in the accepted answer, the object you choose is arbitrary, just make sure you use it correctly. However, some objects are better than others. It's best practice not to use some object that may be accessible outside the context of the locking - if it is some other piece of code may also decide to synchronize on it, or call notify on it or whatever. So preferably use java.util.concurrent instead, or use private objects.

Synchronizing for the formal parameters in java

Let's say I have a method, that is accessed by two or more threads and I want to make it thread safe.
public int getVal(int x, int y, MyClass myObj)
{
int z;
z = getInt(myObj);
return x + y + z;
}
In this, I think we don't have to synchronize for x + y as they are primitives.
Let's assume that getInt(myObj) modifies the state of myObj and that influences the value of z.
Therefore, I will have to provide synchronization for the line z = getInt(myObj); but only when both threads to pass same instance in 'myObj' reference. As the API's coder I would not know whether both threads would pass same instance for 'myObj' or not. In some case these threads might pass same MyClass instance in 'myObj' reference and in other cases they might pass different MyClass-instances in 'myObj' reference.
So, how would one ensure thread-safety for the line z = getInt(myObj)? (Surely, we do not want to synchronize when instances passed are different and only have to synchronize when instances passed are same. I it is clear that this cannot be determined).
Assuming that MyClass cannot be made immutable, I am thinking that the following could be a solution.
synchronized(myObj)
{
z = getInt(myObj);
}
Is it a correct solution? And, in what other ways can we ensure thread safety for
z = getInt(myObj); (but only in case of different instances)?
What you have is correct. When you synchronize on an object its locking on that instance not on that class. So if I pass the same *instance* of an object to two different methods, it will lock on that object correctly. However, if I pass two different instance, there won't be any locking because the two instance have each their own lock.
If getInt doesn't modify the state of this, then the method is thread-safe. The thread-safeness of the myObj object is the responsability of its class : MyClass, or of the object that holds it. Not the responsibility of all the methods which might take it as an argument, IMHO.
Your solution (synchronized(myObj)) is right, though : two threads won't be able to execute the getInt method concurrently if the same myObj is used in both threads. They will execute concurrently if the two myObjs are different.
synchronized(myObj) { z = getInt(myObj); }
will do what you intend, but synchronizing on a paremeter creates many other problems. For example, some other thread may already be syncrhonizing on that object (e.g., maybe that object has a synchronized method which is being called on it) and you could get into a deadlock case.
Synchronization should be encapsulated just like anything else. The best solution would be to add the getInt method to MyClass and synchronize on some private member within that method. This way nobody else can muck with what you are using to implement your sycnrhonization.
E.g.:
public class MyClass {
private Object lockObject = new Object();
public int getInt() {
synchronized(lockObject) {
// do your thing
}
}
}
See this: Avoid synchronized(this) in Java?
in reference to the importance of encapsulating your synchronization.
To answer "And, in what are the ways can we ensure thread safety for...but only in case of different instances", synchronize the entire method or create another, common object to act as a lock for all threads and synchronize on it instead of myObj.
If the only changes on myObject in question come from this getInt method, then your synchronization is enough. If there are other modificators out there, make sure they synchronize on the same object.
I disagree with all "your synchronized is correct" answers. What if you user has 2 threads, and one of them is holding a lock on the object already? Deadlocks ensues.
Also, x + y + z is not atomic. At CPU level, it'll become
int temp = x + y;
int res = temp + z;
I'll tell you more: long1 + long2 is not atomic on 32-bit machines.
I think your only option is to synchronize the entire method.

Categories

Resources