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.
Related
synchronized (lockObject) {
// update some value of the common shared resource
lockObject.wait();
}
As on call of the wait() method, the thread will release the lock, I want to know after releasing the lock does it also update the value in the main memory of the shared resource object or it only updates the value after the execution of the synchronized block.
It is a fallacy to think that due to synchronization (e.g. synchronized or volatile) data needs to be written to main memory. CPU caches on modern CPUs are always coherent due to the cache coherence protocol.
An object.wait causes the thread to release the lock. And as soon as another thread sends a notify, the lock is reacquired. The object.wait has no semantics in the Java memory model; only acquire and release of the lock are relevant.
So in your particular case, if a thread does a wait, it triggers a lock release. If another thread would read that state after acquiring the same lock, then there is a happens-before edge between the thread that did the release of the lock (due to wait) and the thread that acquired the lock. And therefore the second thread is guaranteed to see the changes of the first.
In the JLS 17.4.5 it says
The wait methods of class Object (ยง17.2.1) have lock and unlock actions associated with them; their happens-before relationships are defined by these associated actions.
Also, from JLS 17.4.4:
An unlock action on monitor m synchronizes-with all subsequent lock actions on m (where "subsequent" is defined according to the synchronization order).
If a thread waits it gives up the lock so that other threads can act. It only makes sense that any changes the thread made before waiting (which triggers an unlock action) should be visible to other threads acquiring the lock.
As I understand it, internally obj.join() calls wait(). This means that join() always releases the lock (because wait() always releases the lock after being called).
The API doc explains:
This implementation uses a loop of this.wait calls conditioned on
this.isAlive. As a thread terminates the this.notifyAll method is
invoked. It is recommended that applications not use wait, notify, or
notifyAll on Thread instances.
People here on SO say that join() does not release any lock because the API does not mention it explicitly. But this logic seems strange to me.
Here is the main logic from join()'s code:
while (isAlive()) {
wait(0);
}
This site further adds to the confusion (I think they are mistaken):
3) The third difference between the wait() and join() methods is that when a thread calls the wait() method it releases any lock held for the object on which wait() is called, but calling the join() method doesn't release any monitor or lock.
wait releases the monitor held on the object which wait is invoked on, but not any other monitors.
The current thread must own this object's monitor. The thread releases ownership of this monitor and waits [...].
In other words, given the following:
synchronized (a) {
synchronized (b) {
b.wait();
}
}
At b.wait(), the current thread releases b's monitor, but not a's monitor.
If t.join() is implemented using t.wait() internally, then t's monitor is released while waiting, but not any other monitor.
This join implementation is a case of leaky abstraction, by the way. If Thread used a private final Object monitor; to wait on instead, we could say that join released no monitors, even if it used wait internally without us knowing. There would be no reason to document the implementation detail of using wait, because the monitor would be inaccessible to us, so we would not need to know about it.
The reason that we know join uses wait internally is that the people who originally wrote the method chose a monitor which is accessible to us. This created the need to reveal the implementation details. join is not really supposed to release monitors from our perspective, just wait for a thread to complete, but an implementation was chosen which required us to know more about it than we should.
Though the excellent answer from #Radiodef clarifies & elaborates the leaky abstraction shortcoming, in simpler terms to answer #vrinchvucz confusion the answer is,
Yes, when a thread invokes t.join it does acquire and release 'a' monitor lock. That monitor lock is that of the thread t itself since the implementation of join method on Thread class implemented it by using this.wait inside of the synchronized join method which is the leaky abstraction issue that #Radiodef points to.
Thus unless the thread acquires the monitor lock of t itself before it invokes t.join we can say that NO client/user acquired monitor locks are released in the t.join invocation (because the monitor lock in question is NOT any that the client/user code acquired in the thread that invoked t.join).
This since as clearly stated in the docs for Object#wait
Note that the wait method, as it places the current thread into the
wait set for this object, unlocks only this object; any other objects
on which the current thread may be synchronized remain locked while
the thread waits.
Which is why the docs for Thread#join does not mention anything about locks being released while still giving the implementation details regarding the use of this.wait.
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).
This question already has an answer here:
What's the difference in using ReentrentLock and Synchronized(object)? [duplicate]
(1 answer)
Closed 5 years ago.
I have used the synchronized keyword and re-entrant locks in Java, but I don't understand how they differ, or which is appropriate for a given situation.
How do I decide when should I use synchronized and when I should use re-entrant locks?
A ReentrantLock is:
A reentrant mutual exclusion Lock with the same basic behavior and
semantics as the implicit monitor lock accessed using synchronized
methods and statements, but with extended capabilities.
Extended capabilities include:
The ability to have more than one condition variable per monitor. Monitors that use the synchronized keyword can only have one. This means reentrant locks support more than one wait()/notify() queue.
The ability to make the lock fair. Synchronized blocks are unfair.
"[fair] locks favor granting access to the longest-waiting thread. Otherwise this lock does not guarantee any particular access order."
The ability to check if the lock is being held.
The ability to get the list of threads waiting on the lock.
The disadvantages of reentrant locks are:
Need to add import statement.
Need to wrap lock acquisitions in a try/finally block. This makes it more ugly than the synchronized keyword.
The synchronized keyword can be put in method definitions which avoids the need for a block which reduces nesting.
Summary
The synchronized keyword is syntactically nicer, but the Reentrant lock has more features.
This site clearly mentioned difference between ReentrantLock and synchronized keyword in Java. I just copy and paste from there.
http://javarevisited.blogspot.in/2013/03/reentrantlock-example-in-java-synchronized-difference-vs-lock.html
1) Another significant difference between ReentrantLock and synchronized keyword is fairness. synchronized keyword doesn't support fairness. Any thread can acquire lock once released, no preference can be specified, on the other hand you can make ReentrantLock fair by specifying fairness property, while creating instance of ReentrantLock. Fairness property provides lock to longest waiting thread, in case of contention.
2) Second difference between synchronized and Reentrant lock is tryLock() method. ReentrantLock provides convenient tryLock() method, which acquires lock only if its available or not held by any other thread. This reduce blocking of thread waiting for lock in Java application.
3) One more worth noting difference between ReentrantLock and synchronized keyword in Java is, ability to interrupt Thread while waiting for Lock. 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. Similarly tryLock() with timeout can be used to timeout if lock is not available in certain time period.
4) ReentrantLock also provides convenient method to get List of all threads waiting for lock.
I have always thought of synchronization as "the hack of least resistance". It just works and most everyone understands how it works, but it has some weaknesses that could affect your design under heavy concurrency. Not least of which is any client effectively has direct access to your object's synchronization lock meaning if they grab it and hold it other clients can't. In other words, the locking implemented by default synchronization effectively "publishes" you object's internal locking mechanism. Yuk. Its like setting yourself up for self-inflicted denial-of-service.
If you make the reentrant lock internal to your class (or just don't use the synchronized but do something like synchronize on some internal object that you new up in your constructor everywhere that you want synchronization), you remove this side-effect of publishing your internal locking mechanism, with the added complexity of you having to remember where to apply this internal synchronization as your class evolves.
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.