static array variables would need to be locked? - java

so let's say that I have a static variable, which is an array of size 5.
And let's say I have two threads, T1 and T2, they both are trying to change the element at index 0 of that array. And then use the element at index 0.
In this case, I should lock the array until T1 is finished using the element right?
Another question is let's say T1 and T2 are already running, T1 access element at index 0 first, then lock it. But then right after T2 tries to access element at index 0, but T1 hasn't unlocked index 0 yet. Then in this case, in order for T2 to access element at index 0, what should T2 do? should T2 use call back function after T1 unlocks index 0 of the array?

Synchronization in java is (technically) not about refusing other threads access to an object, it about ensuring unique usage of it (at one time) between threads using synchronization locks. So T2 can access the object while T1 has synchronization lock, but will be unable to obtain the synchronization lock until T1 releases it.

You synchronize (lock) when you're going to have multiple threads accessing something.
The second thread is going to block until the first thread releases the lock (exits the synchronized block)
More fine-grained control can be had by using java.util.concurrent.locks and using non-blocking checks if you don't want threads to block.

1) Basically, yes. You needn't necessarily lock the array, you could lock at a higher level of granularity (say, the enclosing class if it were a private variable). The important thing is that no part of the code tries to modify or read from the array without holding the same lock. If this condition is violated, undefined behaviour could result (including, but not limited to, seeing old values, seeing garbage values that never existed, throwing exceptions, and going into infinite loops).
2) This depends partly on the synchronization scheme you're using, and your desired semantics. With the standard synchronized keyword, T2 would block indefinitely until the monitor is released by T1, at which point T2 will acquire the monitor and continue with the logic inside the synchronized block.
If you want finer-grained control over the behaviour when a lock is contended, you could use explicit Lock objects. These offer tryLock methods (both with a timeout, and returning immediately) which return true or false according to whether the lock could be obtained. Thus you could then test the return value and take whatever action you like if the lock isn't immediately obtained (such as registering a callback function, incrementing a counter and giving feedback to a user before trying again, etc.).
However, this custom reaction is seldom necessary, and notably increases the complexity of your locking code, not to mention the large possibility of mistakes if you forget to always release the lock in a finally block if and only if it was acquired successfully, etc. As a general rule, just go with synchronized unless/until you can show that it's providing a significant bottleneck to your application's required throughput.

I should lock the array until T1 is finished using the element right?
Yes, to avoid race conditions that would be a good idea.
what should T2 do
Look the array, then read the value. At this time you know noone else can modify it. When using locks such as monitors an queue is automatically kept by the system. Hence if T2 tries to access an object locked by T1 it will block (hang) until T1 releases the lock.
Sample code:
private Obect[] array;
private static final Object lockObject = new Object();
public void modifyObject() {
synchronized(lockObject) {
// read or modify the objects
}
}
Technically you could also synchronize on the array itself.

You don't lock a variable; you lock a mutex, which protects
a specific range of code. And the rule is simple: if any thread
modifies an object, and more than one thread accesses it (for
any reason), all accesses must be fully synchronized. The usual
solution is to define a mutex to protect the variable, request
a lock on it, and free the lock once the access has finished.
When a thread requests a lock, it is suspended until that lock
has been freed.
In C++, it is usual to use RAII to ensure that the lock is
freed, regardless of how the block is exited. In Java,
a synchronized block will acquire the lock at the start
(waiting until it is available), and leave the lock when the
program leaves the block (for whatever reasons).

Have you considered using AtomicReferenceArray? http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/atomic/AtomicReferenceArray.html It provides a #getAndSet method, that provides a thread safe atomic way to update indexes.

T1 access element at index 0 first, then lock it.
Lock first on static final mutex variable then access your static variable.
static final Object lock = new Object();
synchronized(lock) {
// access static reference
}
or better access on class reference
synchronized(YourClassName.class) {
// access static reference
}

Related

in Java do i need to mark an int field as volatile if threads increment it only within synchronized method? [duplicate]

In the following simple scenario:
class A {
int x;
Object lock;
...
public void method(){
synchronized(lock){
// modify/read x and act upon its value
}
}
}
Does x need to be volatile? I know that synchronized guarantees atomicity, but I am not sure about visibility though... does lock -> modify -> unlock -> lock guarantee, that after the second lock the value of x will be "fresh"?
No it does not, because synchronized already has a memory barrier inserted after it, so all threads will see the update that the current thread performs, taking into account that the other threads will synchronize on the same lock.
Volatile, just like synchronized, has memory barriers that are attached to it - depending on the CPU, it is store/load/full barrier that ensures that an update from one thread is visible to the other(s). I assume this is performed with CPU cache invalidation.
EDIT
From what I've just read, the store buffers are flushed to the CPU cache, and this is how the visibility is achieved.
Simplified answer: If thread A updates a field and then releases a lock, then thread B will be guaranteed to see the update after thread B has acquired the same lock.
Note, "release a lock" means exit a synchronized block, and "acquire the same lock" means synchronize on the same object.

Re-Check mutable reference for "synchronized" lock?

I'm wondering if there is an easy way to make a synchronized lock that will respond to changing references. I have code that looks something like this:
private void fus(){
synchronized(someRef){
someRef.roh();
}
}
...
private void dah(){
someRef = someOtherRef;
}
What I would like to happen is:
Thread A enters fus, and acquires a lock on someref as it calls roh(). Assume roh never terminates.
Thread B enters fus, begins waiting for someRef` to be free, and stays there (for now).
Thread C enters dah, and modifies someRef.
Thread B is now allowed to enter the synchronized block, as someRef no longer refers to the object Thread A has a lock on.
What actually happens is:
Thread A enters fus, and acquires a lock on someref as it calls roh(). Assume roh never terminates.
Thread B enters fus, finds the lock, and waits for it to be released (forever).
Thread C enters dah, and modifies someRef.
Thread B continues to wait, as it's no longer looking at someref, it's looking at the lock held by A.
Is there a way to set this up such that Thread B will either re-check the lock for changing references, or will "bounce off" into other code? (something like sychronizedOrElse?)
There surely is a way, but not with synchronized. Reasoning: At the point in time, where the 2nd thread enters fus(), the first thread holds the intrinsic lock of the object referenced by someRef. Important: the 2nd thread will still see someRef referencing on this very object and will try to acquire this lock. Later on, when the 3rd thread changes the reference someRef, it would have to notify the 2nd thread somehow about this event. This is not possible with synchronized.
To my knowledge, there is no built-in language-feature like synchronized to handle this kind of synchronization.
A somewhat different approach would be to either manage a Lock within your class or give someRef an attribute of type Lock. Instead of working with lock() you can use tryLock() or tryLock(long timeout, TimeUnit unit). This is a scheme on how I would implement this (assuming that someRef has a Lock attribute):
volatile SomeRef someRef = ... // important: make this volatile to deny caching
...
private void fus(){
while (true) {
SomeRef someRef = this.someRef;
Lock lock = someRef.lock;
boolean unlockNecessary = false;
try {
if (lock.tryLock(10, TimeUnit.MILLISECONDS)) { // I have chonse this arbritrarily
unlockNecessary = true;
someRef.roh();
return; // Job is done -> return. Remember: finally will still be executed.
// Alternatively, break; could be used to exit the loop.
}
} catch (InterruptException e) {
e.printStackTrace();
} finally {
if (unlockNecessary) {
lock.unlock();
}
}
}
}
...
private void dah(){
someRef = someOtherRef;
}
Now, when someRef is changed, the 2nd thread will see the new value of someRef in its next cycle and therefore will try to synchronize on the new Lock and succeed, if no other thread has acquired the Lock.
What actually happens is ... Thread B continues to wait, as it's no longer looking at someref, it's looking at the lock held by A.
That's right. You can't write code to synchronize on a variable. You can only write code to synchronize on some object.
Thread B found the object on which to synchronize by looking at the variable someref, but it only ever looks at that variable one time to find the object. The object is what it locks, and until thread A releases the lock on that object, thread B is going to be stuck.
I would like to add some more info on top of excellent answers by #Turing85 and #james large.
I agree that Thread B continues to wait.
It's better to avoid synchronization for this type of program by using better lock free API.
Atomic variables have features that minimize synchronization and help avoid memory consistency errors.
From the code you have posted, AtomicReference seems to be right solution for your problem.
Have a look at documentation page on Atomic package.
A small toolkit of classes that support lock-free thread-safe programming on single variables. In essence, the classes in this package extend the notion of volatile values, fields, and array elements to those that also provide an atomic conditional update operation of the form:
boolean compareAndSet(expectedValue, updateValue);
One more nice post in SE related to this topic.
When to use AtomicReference in Java?
Sample code:
String initialReference = "value 1";
AtomicReference<String> someRef =
new AtomicReference<String>(initialReference);
String newReference = "value 2";
boolean exchanged = someRef.compareAndSet(initialReference, newReference);
System.out.println("exchanged: " + exchanged);
Refer to this jenkov tutorial for better understanding.

Non-volatile variable value during wait() and notifyall() call in 2 threads

Lets say I have two threads A and B and inside these both 2 threads I have synchronized block in which an int variable is modified continously.
For example, thread A enter synchronized block modify int variable then call these 2 methods:
notifyall(); //to wake thread B which is in waiting state and
wait():
and after that thread B acquire lock and do same steps as thread A and process keep on repeating. All changes to int variable happens inside synchronized block of both threads.
My question is do I need to make int variable volatile. Do thread flush to main memory before they go to waiting state and reload data in registers when thread acquire lock again as a result of notifyall(); call.
If A and B run alternatively rather than concurrently, and if they switch off via wait() and notifyAll() invocations on the same Object, and if no other threads access the variable in question, then thread safety does not require the variable to be volatile.
Note that o.wait() and o.notifyAll() must be invoked inside a method or block synchronized on o -- that synchronization is sufficient to ensure that the two threads see all each others' writes to any variable before the switch-off.
Do be careful to ensure that the two threads are synchronizing on the same object, which is not clear from your question. You have no effective synchronization at all if, say, the two threads are waiting on and notifying different instances of the same class.
The answer is no you do not need to make the variable volatile. The reasoning being, writes that occur to a variable within a synchronized block will be visible to subsequent threads entering a synchronized block on the same object.
So it has the same memory semantics as a volatile read and write.
Not sure about java. But in C: https://www.kernel.org/doc/Documentation/volatile-considered-harmful.txt
If shared_data were declared volatile, the locking would still be
necessary. But the compiler would also be prevented from optimizing access
to shared_data within the critical section, when we know that nobody else
can be working with it. While the lock is held, shared_data is not
volatile. When dealing with shared data, proper locking makes volatile
unnecessary - and potentially harmful.

If I simply need to guarantee `happens-before` relation, and not atomicity, should I use a concurrent class or a synchronized block?

I am developing a pool mechanism. Objects in the pool will be used by different threads. Thus I need to guarantee that there will be a happens-before relation when accessing non-final attributes of these objects.
As a given object will be accessed by only one thread at a time, I do not need to guarantee any atomicity. What is more optimized when only happens-before needs to be achieved? To use a synchronized block on a final attribute each time I read or modify one of the non-final attribute? Or to use concurrent classes, such as a ConcurrentMap?
(I am not asking this question for attributes of the pool itself, that obviously needs to provide atomicity; I am only asking this question for the attributes of objects obtained from the pool)
To use a synchronized block on a final attribute each time I read or
modify one of the non-final attribute? Or to use concurrent classes,
such as a ConcurrentMap?
Synchronization is built around an internal entity known as the intrinsic lock or monitor lock. Every object has an intrinsic lock associated with it. By convention, a thread that needs exclusive and consistent access to an object's fields has to acquire the object's intrinsic lock before accessing them, and then release the intrinsic lock when it's done with them.
An implementation of ConcurrentMap i.e., ConcurrentHashMap uses reentrant lock which is mutual exclusive lock, Lock is acquired by lock() method and held by Thread until a call to unlock() method. Though, ReentrantLock provides same visibility and orderings guaranteed as implicit lock, acquired by synchronized keyword, it provides more functionality and differ in certain aspect:
ReentrantLock can be made fair by specifying fairness property to provides lock to longest waiting thread, in case of contention.
provides convenient tryLock() method to acquires lock, only if its available or not held by any other thread, reducing blocking of thread waiting for lock. tryLock() with timeout can be used to timeout if lock is not available in certain time period.
In case of synchronized keyword, a thread can be blocked waiting for lock, for an indefinite period of time and there was no way to control that. ReentrantLock provides a method called lockInterruptibly(), which can be used to interrupt thread when it is waiting for lock.
An example of use reentrant lock can be shown from ConcurrentHashMap's inner replace(K key, V oldValue, V newValue) function implementaion:
boolean replace(K key, int hash, V oldValue, V newValue) {
// called by replace(K key, V oldValue, V newValue)
lock(); // acquire the lock
try {
HashEntry<K,V> e = getFirst(hash);
while (e != null && (e.hash != hash || !key.equals(e.key)))
e = e.next;
boolean replaced = false;
if (e != null && oldValue.equals(e.value)) {
replaced = true;
e.value = newValue;
}
return replaced;
} finally {
unlock(); // unlock
}
}
There are other functions like put(), writeObject(java.io.ObjectOutputStream), etc. are also implemented using reentrant synchronization using the ReentrantLock, without which, synchronized code would have to take many additional precautions to avoid having a thread cause itself to block. That is why I think for your case ConcurentMap is preferable.
Reference:
Intrinsic Locks and Synchronization
ReentrantLock Class
Difference between synchronized vs ReentrantLock
ConcurrentHashMap
As a given object will be accessed by only one thread at a time, I do
not need to guarantee any atomicity.
If I get it right, what you mean is that your objects will be shared accross threads, but there is actually no concurrency going on (objects are never accessed concurrently by multiple threads). You're wondering what synchronization is needed.
I've been wondering the same, and my conclusion was the following: if object Y synchronizes accesses to object X, object X doesn't need to be synchronized itself. In the case of a pool, you probably obtain and release objects using methods that are synchronized, so they protect the object in the pool.
Let's consider object O in the pool. The pool has two methods Object acquire() and release(Object o) that are synchronized. To pass object O from thread T1 to T2, T1 must first release O, and T2 must then acquire O. There is already a happen-before relationship between T1's release and T2's acquire, so the object O doesn't need to be itself synchronized.
If the field you need the happens-before relationship on is a primitive, and you are using Java 5 or later, then you can use the volatile keyword which in Java 5+ ensures happens-before reading.
If it's an object, then you need to use some kind of synchronization either using the synchronized key word or a class from the java.util.concurrent package which often has better performance than naive synchronization. For example, ConcurrentHashMap usually has better performance than Collections.synchronizedMap(Map) because it uses separate locks for each bin so there is less lock contention.
well if you need to guarantee a Happens-Before, i think you can create a Synchronized block, holding the Object you want to lock, then in this block, do what you want it to be done before using this object, then invoke your stuff from the Object, then release
for instance
public void doSomething(){
synchronized(myObject){
doAnotherThing();
myObject.doStuff();
}
}
i didnt try the ConcurrentMap before by the way ... and by the way, please clarify your example because i think i didnt get you right !!

Can the synchronized statements be re-ordered by Java compiler for optimization?

Can the synchronization statements be reordered. i.e :
Can :
synchronized(A) {
synchronized(B) {
......
}
}
become :
synchronized(B) {
synchronized(A) {
......
}
}
Can the synchronization statements be reordered?
I assume you are asking if the compiler can reorder the synchronized blocks so the lock order happens in a different order than the code.
The answer is no. A synchronized block (and a volatile field access) impose ordering restrictions on the compiler. In your case, you cannot move a monitor-enter before another monitor-enter nor a monitor-exit after another monitor-exit. See the grid below.
To quote from JSR 133 (Java Memory Model) FAQ:
It is not possible, for example, for the compiler to move your code before an acquire or after a release. When we say that acquires and releases act on caches, we are using shorthand for a number of possible effects.
Doug Lea's JSR-133 Cookbook has a grid which shows the reordering possibilities. A blank entry in the grid means that reordering is allowed. In your case, entering a synchronized block is a "MonitorEnter" (same reordering limitations as loading of a volatile field) and exiting a synchronized block is a "MonitorExit" (same as storing to a volatile field).
Yes and no.
The order must be consistent.
Suppose you are creating a transaction between two bank accounts, and always grab the sender's lock first, then grab the receiver's lock. Problem is - say both Dan and Bob want to transfer money to each other at the same time.
Thread 1 might grab Dan's lock, as it processes Dan's transaction to Bob.
Then thread 2 grab's Bob's lock, as it processes Bob's transaction to Dan.
Then, bam, deadlock.
The morals are:
Lock less.
Read Java: Concurrency in Practice. My example is taken from there. I like arguing about the merits of books in programming as much as the next guy, but it's pretty rare you get comprehensive coverage of a difficult topic between two covers, so enjoy it.
So this is the part of the answer where I guess at other things you might have been trying to ask instead, because the expectation is firmly on me that I act psychic.
The JVM will not acquire the locks in an order different from which you have programmed. How do I know this? Because otherwise it would not be possible to solve the problem in the first half of my answer.
Synchronized statements are never reordered by the compiler as it has a big effect on what ends up happening.
Synchronized blocks are used to obtain a lock on the specific Object placed between the synchronized parenthesis.
private final Object LOCK_1 = new Object();
public void foo(){
synchronized(LOCK_1){
//code here...
}
}
Obtains the lock for Object LOCK_1 and releases it when the synchronization block completes. Since synchronization blocks are used to guard against concurrent access it may be sometimes required to use multiple locks especially when multiple thread-unsafe objects are being written/read to/from.
Consider the following code that uses a nested synchronization block:
private final Object LOCK_1 = new Object();
private final Object LOCK_2 = new Object();
public void bar(){
synchronized(LOCK_1){
//Point A
synchronized(LOCK_2){
//Point B
}
//Point C
}
//Point D
}
If we look at points A,B,C,D we can realize why the order of synchronization matters.
First at point A, the lock for LOCK_1 is obtained therefore any other threads trying to obtain LOCK_1 is put into a queue.
At point B, the currently executing thread owns the lock for both LOCK_1 and LOCK_2.
At point C, the currently executing thread has released the lock for LOCK_2
At point D, the currently executing thread has released all locks.
If we flip this example around and decided to put LOCK_2 on the outer block, you will realize that the thread's order of obtaining locks changes which has a big effect on what it ends up doing. Normally, when I make programs with synchronization blocks I use one MUTEX object per thread-unsafe resource I am accessing (or one MUTEX per group). Say I want to read from a stream using LOCK_1 and write to a stream using LOCK_2. It would be illogical to think that swapping the locking order around means the same thing.
Consider that LOCK_2 (the writing lock) is being held by another thread. If we have LOCK_1 on the outer block the currently executing thread can at least process all the reading code before being put into a queue for the writing lock (essentially, the ability to execute code at point A). If we flipped the order of the locks around, the currently executing thread will end up having to wait for the writing is complete, then proceed onto reading and writing whilst holding onto the writing lock (all the way through reading too).
Another problem that comes up when the order of locks are switched (and not consistently, some code has LOCK_1 first and others have LOCK_2 first). Consider that two threads both eagerly try to execute code which have different locking orders. Thread 1 obtains LOCK_1 in the outer block and thread 2 obtains LOCK_2 from the outer block. Now when thread 1 tries to obtain LOCK_2, it can't since thread 2 has it. And when thread 2 tries to obtain LOCK_1, it can't either because thread 1 has it. The two threads essentially block on each other forever, forming a deadlock situation.
To answer your question, if you want to lock on two objects immediately without doing any sort of processing between locks then the order is irrelevant (essentially no processing at point A or C). HOWEVER it is essential to keep the order consistent throughout your program as to avoid deadlocking.

Categories