When applying a reentrantReadWriteLock, and it is locked, what happens if another thread accesses the Lock while it is already performing another block? (Thus, before it reaches the .unlock)
Is the method canceled out? Or perhaps it's stalled? :O
Since you said ReentrantReadWriteLock, the behavior depends on whether you're talking about taking the read lock or the write lock associated with the ReadWriteLock.
If you're trying to acquire the write lock, you will be blocked until all holders release the lock (whether it is the read lock or the write lock)
If you're trying to acquire the read lock and there is no holder of the write lock, you will always be able to acquire it even if there are other read lock holders
If you're trying to acquire the read lock and there is a holder of the write lock, you will be blocked until the write lock holder releases the write lock
The read lock can be held concurrently by multiple threads as long as there is no writer.
The thread will block until the lock is available. (docs)
If you only want to acquire the lock if its available, you can use tryLock()
The thread will block. If more than one thread tries to acquire this lock, all of them will be blocked. When the lock is released, exactly one thread from the waiting pool will acquire the lock and the rest will still wait. See the difference between fair and unfair locks.
If you don't want to block you can use Lock.tryLock() (which tries without waiting) or tryLock(long time, TimeUnit unit) which will wait only as long as you specify.
Related
How does the java thread acquire a lock on a monitor used in synchronized block or monitor used in synchronized methods?
I read on multiple posts that in case of biased locking this information is stored in the object header using CAS operation and in case of contended situation wait set queue/ monitor queue is used but eventually lock marked in the object header only.
If this is the case then how is lock released? How object is marked free for acquiring a lock by another thread? are wait and notify methods used internally for this? If this is the case then why is making monitor null inside the synchronized block does not throw any exception.
The below example works perfectly fine, I was expecting NullPointerException assuming the end of the synchronized block will try to mark lock property to free the lock.
Example:
Object monitor = new Object();
synchronized (monitor){
System.out.println("before null");
monitor =null;
System.out.println("after null");
}
System.out.println("successfully Exited");
In case of biased locking: if the lock is biased towards a certain thread, no CAS is needed; just a volatile write. Biased lock information is kept in the mark word of the object header. Biased locking is going to be removed from JDK 15.
If a lock is contended, the object-monitor is used for synchronization. By default the object monitor is deflated, but if there is contention or you do a wait/notify, then the monitor gets inflated and is attached to the object.
On Linux blocking behavior is implemented using a wait-queue. So when a thread needs to wait for a lock, it is removed from the scheduler and added to the wait queue. When a lock unlocks, the thread on the wait queue is reinserted back into the scheduler.
The reason why the code doesn't throw an exception is that the monitor is read only once when the synchronized block is entered.
PS: It could be that your lock get completely removed due to lock elision. If the JIT can provide no other thread can acquire that lock, there is no point in synchronizing.
I am investigating Java concurrency and I've found one interesting question which I cannot answer.
For example, I have three threads: ThreadA, ThreadB and ThreadC. ThreadA enters the monitor, and invokes method wait(). Then ThreadB enters the same monitor, invokes method notify() and continue owning the monitor during some period of time. While ThreadB is owning the monitor, ThreadC tries to acquire the monitor too. My question is whether ThreadC can acquire the monitor earlier then ThreadA when ThreadB release it or not? If it can, why? Which conditions should be followed to reproduce it?
As per the Javadoc on Object.notify():
The awakened thread will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened thread enjoys no reliable privilege or disadvantage in being the next thread to lock this object.
So there exists the possibility that ThreadC owns the monitor before ThreadA. There is no defined order in which any of the threads enter/obtain the monitor, nor is there any priority or fairness mechanism in place for standard synchronization. All it really guarantees is that for a given lock object, only on thread will be in the synchronized block at once.
Given this fact, careful design considerations should go into how threads obtain the lock and for how long. A thread that repeatedly attempts to acquire a lock (acquire and then release but then acquire again) can cause another thread to be locked out indefinitely (called thread starvation).
Using ReentrantLock with a fairness policy can partially overcome this issue at some performance cost (its slightly slower than traditional synchronization).
Hi my question is how synchronization works?
In simple words we know that if a thread entered in a synchronization block by acquiring lock on any reference, than no other thread acquire that lock until first one exit from synchronized block.
But my question is if the thread acquired a lock on a reference and execute methodA() in that method there is a synchronized block, than can other thread acquire a lock on same reference and execute methodB(), there is also a synchronized block in it?
Synchronization is for mutual exclusion
Whenever you synchronize on an object, a lock is obtained on the monitor of that object.
Image Source: Thread synchronization
As the image shows as whenever a thread acquires a lock on monitor then it becomes the owner thread and no other thread can obtain lock on same monitor unless the owner thread enters wait state or releases the lock.
That said another point to keep in mind is that locks that are used in synchronized blocks are Reentrant, which means that if Thread 1 is the owner of the lock and same thread again tries to gain lock of which it is owner then Java will allow that.
Ok, than i have a issue. synchronized(b){ try{ b.wait();
}catch(InterruptedException e){} now as i acquired a lock on b object,
it means no other thread can acquire a lock on b object.
On calling wait(), the owner thread releases the lock and goes in Wait Set as shown in diagram. After that someone else from Entry set can get the lock.
I believe that the second lock will have to wait till the first lock has been released.
Have a look at the link Java synchronized references for more information.
Synchronization is very simple
One Thread locks any number of objects.
Only one thread can lock a given object at a given time.
When attempting to lock an object that is already locked by another thread, a thread has to wait until the object is released.
A Thread in wait state releases the locks it holds until it exists the wait state (at which time it attempts to reacquire the locks previously held).
In java, a lock is acquired using a synchronized block.
To answer your question: 2 threads can never acquire a lock on the same object at the same time.
What is Upgrade/Downgrade of ReentrantReadWriteLock?
I see javadoc about Upgrade/Downgrade:
"Lock downgrading :
Reentrancy also allows downgrading from the write lock to a read lock, by acquiring the write lock, then the read lock and then releasing the write lock. However, upgrading from a read lock to the write lock is not possible."
And a sample provided:
class CachedData {
Object data;
volatile boolean cacheValid;
ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
void processCachedData() {
rwl.readLock().lock();
if (!cacheValid) {
// upgrade lock manually
rwl.readLock().unlock(); // must unlock first to obtain writelock
rwl.writeLock().lock();
if (!cacheValid) { // recheck
data = ...
cacheValid = true;
}
// downgrade lock
rwl.readLock().lock(); // reacquire read without giving up write lock
rwl.writeLock().unlock(); // unlock write, still hold read
}
use(data);
rwl.readLock().unlock();
}
}
I know it talks about the relation between readLock and writeLock, but I couldn't get the clear concept from the doc. Could you give me a little more explanation? Thanks!
I believe that in this context the idea of "upgrading" and "downgrading" is based on the idea that the reader lock is, in a sense, a "weaker" lock than the writer lock. When the write lock is acquired, no other threads can acquire the lock in any form, whereas with a reader lock any other thread can acquire the read lock if it wants to.
Here, "downgrading" the lock means that if you hold the write lock, you can switch down to holding just the read lock by acquiring the read lock, then releasing the write lock. This means that you can have a thread that starts off doing something critically important (something that would prevent other threads from reading), does its work, and then switches to the lower-priority lock (the read lock) without ever being without the lock. This allows you to hold the lock continuously without getting preempted.
However, the other way doesn't work - once you're holding the read lock, you can't "upgrade" to holding the more important write lock by trying to acquire the write lock. If you tried to do this, the thread would just block until it was interrupted.
Hope this helps!
I need to implement the following scenario
ThreadN acquires a lock
ThreadM tries to acquire the lock and wait
ThreadX (monitor) sees that ThreadN is holding lock too long time and releases the lock
ThreadM acquires the lock and continue
Fate of ThreadN does not matter.
Which classes (from java.util.concurrent ?) should I use ?
I think you can implement this based on Semaphore, though you'll have to implement the monitoring functionality yourself by setting a timestamp when a lock is acquired, checking it periodically and interrupting the thread holding the lock if it's held too long.
The LockSupport class also looks like it could help.
Afaik you can't.
Locking in Java is cooperative - if a Thread acquires a lock on an Object you can not force it to release lock from another Thread.
All java.util.concurrent classes build upon basic Java locking features (synchronize/wait/notify) so they have no such capability.
What you should do is write ThreadN so that it releases a lock occasionally. You could do this using basic locking constructs (synchronize/wait/notify) by adding an atomic variable (boolean) that signalizes that another thread needs a lock. Then ThreadN would release the lock.
Alternatively use so higher-level java.util.concurrent class such as Lock.