Deadlocks only seem possible if there is a cyclic dependency created by the possibility of one or more threads creating a loop through lockable resources.
One option is to avoid these cycles through careful static analysis or through a design pattern for acquiring locks.
However can we prevent deadlocks by using tryLock on the Lock interface?
tryLock attemps to get the lock atomically, and returns true if successful, if its already locked then it returns false so we can simply skip over the code.
int sharedStateA = 0;
int sharedStateB = 0;
Lock lockA = new ReentrantLock();
Lock lockB = new ReentrantLock();
// possible deadlock safe solution
// executed by thread 1
void deadLockSafeUpdateAthenB(){
try {
if (lockA.tryLock()){
sharedStateA = sharedStateA + 1;
try {
if (lockB.tryLock()){
sharedStateB = sharedStateB + 1;
}
} finally {
lockB.unlock();
}
}
} finally {
lockA.unlock();
}
}
// executed by thread 2
void deadLockSafeUpdateBthenA(){
try {
if (lockB.tryLock()){
sharedStateB = sharedStateB + 1;
try {
if (lockA.tryLock()){
sharedStateA = sharedStateA + 1;
}
} finally {
lockA.unlock();
}
}
} finally {
lockB.unlock();
}
}
Your code with Lock.tryLock() is deadlock safe but you should try to use the other method,
public boolean tryLock(long timeout,
TimeUnit unit)
if your threads have short run times. The call - tryLock(0,TimeUnit.SECONDS) is better than Lock.tryLock() because it honors fairness policy i.e. lock waiting queue is honored while tryLock() doesn't honor that.
Even if a static analysis tells us that a code is deadlock prone but its not always necessary that a deadlock prone code will actually produce deadlocks since its all an unlucky timing game so your target with tryLock() should be to produce functionally the same program as with deadlock prone code assuming that deadlock doesn't occur.
Fixing one problem shouldn't introduce other issues and in your code it looks quite possible that at some unlucky timing, one thread might not execute at all so I suggest to use timed trylock instead of barging trylock if its mandatory for lock acquisition to be in that order.
Hope it helps !!
Related
I have a piece of code that on startup creates a HashMap of key to ReentrantLock.
void constructor() {
this.lockMap = new HashMap<>();
for (int i=0; i<100; i++) {
this.lockMap.put(i, new ReentrantLock(true));
}
}
During concurrent execution, I try to lock the lock inside the lockMap in the following manner:
runConcurrently() {
ii = 10;
if (!lockMap.containsKey(ii)) {
log.error("lock id is not found in the lockMap " + ii);
}
locked = lockMap.get(ii).tryLock();
if (!locked) {
return;
}
runCriticialSection();
lockMap.get(ii).unlock();
}
void runCriticialSection() {
log.info("hello");
log.info("I'm here");
}
so here is what I have seen happen once in while every 4 hours the code is running, in a very rare occurrence.
I see these logs:
hello.
hello.
I'm here.
I'm here.
and then I see this log right after on third time accessing the hasmap on the same key ii =10:
lock id is not found in the map 10.
NullPointerExeception ... trying to access the map.
where I should see in guaranteed ordering:
hello.
I'm here.
hello.
I'm here.
The Hashmap never gets modified during execution at all.
is there an issue with hashmap not being concurrent hashmap? is get, not threadsafe in absence of modifications? I am specifically not using it due to locking slowness in concurrent hasmap. But the hashmap is only created on startup and never modified after. I find it very weird where it seems the lock has been acquired twice and it seems like the element is missing from the map.
There is no concurrency issue with the map itself, if the map is never modified after the constructor. If so, threads will only ever see that final version of the map. Else, the behaviour is undefined.
No exclusive access of the critical section
From your output, it appears that (at least) two threads accessed runCriticialSection simultaneously.
This is due to the fact that you are using a different lock for each value of ii. A lock only excludes another thread from locking it, if that other threads uses that same lock! Thus, threads that do not use the same value of ii, will effortlessly run runCriticialSection simultaneously. That can result in the described output anomaly as shown above, as follows:
Thread 1 executes log.info("hello");
Thread 2 executes log.info("hello");
Thread 1 executes log.info("I'm here");
Thread 2 executes log.info("I'm here");
If you want exclusive access to a section, always use the same lock surrounding that section.
Coding problems
When the check fails that ii maps to a lock, you should not continue but instead return or throw an exception. If you don't, locked = lockMap.get(ii).tryLock(); throws a NullPointerExcetpion, because lockMap.get(ii) returns null.
Between locking the lock and unlocking it, you are running user code, in the form of runCriticalSection. If you change the implementation of that method later and it starts throwing things: your lock will never unlock! Always use try ... finally with a lock.
Fixing these issues, could lead to the following code:
if (!lockMap.containsKey(ii)) {
log.error("lock id is not found in the lockMap " + ii);
return;
}
locked = lockMap.get(ii).tryLock();
if (!locked) {
return;
}
try {
runCriticialSection();
}
finally {
lockMap.get(ii).unlock();
}
Actually, I would just put the lock in a local variable, but that is a matter of opinion.
ReentrantLock lock = lockMap.get(ii);
if (lock == null) {
log.error("lock id is not found in the lockMap " + ii);
return;
}
locked = lock.tryLock();
if (!locked) {
return;
}
try {
runCriticialSection();
}
finally {
lock.unlock();
}
I was trying to implement something similar to Java's bounded BlockingQueue interface using Java synchronization "primitives" (synchronized, wait(), notify()) when I stumbled upon some behavior I don't understand.
I create a queue capable of storing 1 element, create two threads that wait to fetch a value from the queue, start them, then try to put two values into the queue in a synchronized block in the main thread. Most of the time it works, but sometimes the two threads waiting for a value start seemingly waking up each other and not letting the main thread enter the synchronized block.
Here's my (simplified) code:
import java.util.LinkedList;
import java.util.Queue;
public class LivelockDemo {
private static final int MANY_RUNS = 10000;
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < MANY_RUNS; i++) { // to increase the probability
final MyBoundedBlockingQueue ctr = new MyBoundedBlockingQueue(1);
Thread t1 = createObserver(ctr, i + ":1");
Thread t2 = createObserver(ctr, i + ":2");
t1.start();
t2.start();
System.out.println(i + ":0 ready to enter synchronized block");
synchronized (ctr) {
System.out.println(i + ":0 entered synchronized block");
ctr.addWhenHasSpace("hello");
ctr.addWhenHasSpace("world");
}
t1.join();
t2.join();
System.out.println();
}
}
public static class MyBoundedBlockingQueue {
private Queue<Object> lst = new LinkedList<Object>();;
private int limit;
private MyBoundedBlockingQueue(int limit) {
this.limit = limit;
}
public synchronized void addWhenHasSpace(Object obj) throws InterruptedException {
boolean printed = false;
while (lst.size() >= limit) {
printed = __heartbeat(':', printed);
notify();
wait();
}
lst.offer(obj);
notify();
}
// waits until something has been set and then returns it
public synchronized Object getWhenNotEmpty() throws InterruptedException {
boolean printed = false;
while (lst.isEmpty()) {
printed = __heartbeat('.', printed); // show progress
notify();
wait();
}
Object result = lst.poll();
notify();
return result;
}
// just to show progress of waiting threads in a reasonable manner
private static boolean __heartbeat(char c, boolean printed) {
long now = System.currentTimeMillis();
if (now % 1000 == 0) {
System.out.print(c);
printed = true;
} else if (printed) {
System.out.println();
printed = false;
}
return printed;
}
}
private static Thread createObserver(final MyBoundedBlockingQueue ctr,
final String name) {
return new Thread(new Runnable() {
#Override
public void run() {
try {
System.out.println(name + ": saw " + ctr.getWhenNotEmpty());
} catch (InterruptedException e) {
e.printStackTrace(System.err);
}
}
}, name);
}
}
Here's what I see when it "blocks":
(skipped a lot)
85:0 ready to enter synchronized block
85:0 entered synchronized block
85:2: saw hello
85:1: saw world
86:0 ready to enter synchronized block
86:0 entered synchronized block
86:2: saw hello
86:1: saw world
87:0 ready to enter synchronized block
............................................
..........................................................................
..................................................................................
(goes "forever")
However, if I change the notify() calls inside the while(...) loops of addWhenHasSpace and getWhenNotEmpty methods to notifyAll(), it "always" passes.
My question is this: why does the behavior vary between notify() and notifyAll() methods in this case, and also why is the behavior of notify() the way it is?
I would expect both methods to behave in the same way in this case (two threads WAITING, one BLOCKED), because:
it seems to me that in this case notifyAll() would only wake up the other thread, same as notify();
it looks like the choice of the method which wakes up a thread affects how the thread that is woken up (and becomes RUNNABLE I guess) and the main thread (that has been BLOCKED) later compete for the lock — not something I would expect from the javadoc as well as searching the internet on the topic.
Or maybe I'm doing something wrong altogether?
Without looking too deeply into your code, I can see that you are using a single condition variable to implement a queue with one producer and more than one consumer. That's a recipe for trouble: If there's only one condition variable, then when a consumer calls notify(), there's no way of knowing whether it will wake the producer or wake the other consumer.
There are two ways out of that trap: The simplest is to always use notifyAll().
The other way is to stop using synchronized, wait(), and notify(), and instead use the facilities in java.util.concurrent.locks.
A single ReentrantLock object can give you two (or more) condition variables. Use one exclusively for the producer to notify the consumers, and use the other exclusively for the consumers to notify the producer.
Note: The names change when you switch to using ReentrantLocks: o.wait() becomes c.await(), and o.notify() becomes c.signal().
There appears to be some kind of fairness/barging going on using intrinsic locking - probably due to some optimization. I am guessing, that the native code checks to see if the current thread has notified the monitor it is about to wait on and allows it to win.
Replace the synchronized with ReentrantLock and it should work as you expect it. The different here is how the ReentrantLock handles waiters of a lock it has notified on.
Update:
Interesting find here. What you are seeing is a race between the main thread entering
synchronized (ctr) {
System.out.println(i + ":0 entered synchronized block");
ctr.addWhenHasSpace("hello");
ctr.addWhenHasSpace("world");
}
while the other two thread enter their respective synchronized regions. If the main thread does not get into its sync region before at least one of the two, you will experience this live-lock output you are describing.
What appears to be happening is that if both the two consumer threads hit the sync block first they will ping-pong with each other for notify and wait. It may be the case the JVM gives threads that are waiting priority to the monitor while threads are blocked.
Update:
When I first posted this, I was fairly certain the code was broken. Now, I'm no longer sure about what I'd observed. The biggest problem I'm having is that I can't seem to apply 17.4. Memory Model and state straight out whether it should or shouldn't work.
This following code is broken.
It's overly complex for what it's trying to achieve, but furthermore, it's thread-unsafe in that I've observed that it can indefinitely wait at c. I'm not worried about the former (one could use a ReentrantLock or CountDownLatch for sounder code), but I'm wondering, what's the reason for the latter?
static final ConcurrentHashMap<Integer, Object> mutex = new ConcurrentHashMap<>();
public static brokenFoo() {
Object ourLock = new Object();
for (;;) {
Object theirLock = mutex.putIfAbsent(0, ourLock);
if (theirLock == null) {
break;
}
synchronized (theirLock) { // a
if (mutex.get(0) != theirLock) { // b
continue;
}
theirLock.wait(); // c
} // d
}
try {
// critical section
} finally {
synchronized (ourLock) { // e
mutex.remove(0); // f
ourLock.notifyAll(); // g
} // h
}
}
I've thought in terms of happens-befores:
hb(f, h) and hb(h, a) therefore hb(f, a)
hb(c, d) and hb(d, e) therefore hb(c, e)
But, this doesn't seem to prove or disprove anything.
Edit: (Above question fails to really explain what this code should do.)
Expected:
brokenFoo() is called by multiple threads and the above code is supposed to provide mutual exclusion over // critical section.
If two or more threads enter brokenFoo() at the same time, only one should proceed to // critical section, while others wait somewhere prior.
After the thread in // critical section has exited, another should proceed to take its place.
Actual:
It's been observed that there're threads that are waiting at c even though no other threads are in brokenFoo().
It might be the case that one thread calls notifyAll() before another thread starts to wait(). This may happen due to a spurious wakeup:
thread 1 enters the critical section
thread 2 starts to wait()
a spurious wakeup occurs in thread 2
thread 1 enters the synchronized block and notifies on the lock
thread 2 enters the synchronized block and waits indefinitely
Or thread 1 just happened to execute before thread 2. While your code is correct in terms of the JMM, its liveness is not guaranteed. That's why you should use a CountDownLatch instead of the notify/wait mechanism.
I am on my way learning Java multithread programming. I have a following logic:
Suppose I have a class A
class A {
ConcurrentMap<K, V> map;
public void someMethod1 () {
// operation 1 on map
// operation 2 on map
}
public void someMethod2 () {
// operation 3 on map
// operation 4 on map
}
}
Now I don't need synchronization of the operations in "someMethod1" or "someMethod2". This means if there are two threads calling "someMethod1" at the same time, I don't need to serialize these operations (because the ConcurrentMap will do the job).
But I hope "someMethod1" and "someMethod2" are mutex of each other, which means when some thread is executing "someMethod1", another thread should wait to enter "someMethod2" (but another thread should be allowed to enter "someMethod1").
So, in short, is there a way that I can make "someMethod1" and "someMethod2" not mutex of themselves but mutex of each other?
I hope I stated my question clear enough...
Thanks!
I tried a couple attempts with higher-level constructs, but nothing quite came to mind. I think this may be an occasion to drop down to the low level APIs:
EDIT: I actually think you're trying to set up a problem which is inherently tricky (see second to last paragraph) and probably not needed (see last paragraph). But that said, here's how it could be done, and I'll leave the color commentary for the end of this answer.
private int someMethod1Invocations = 0;
private int someMethod2Invocations = 0;
public void someMethod1() {
synchronized(this) {
// Wait for there to be no someMethod2 invocations -- but
// don't wait on any someMethod1 invocations.
// Once all someMethod2s are done, increment someMethod1Invocations
// to signify that we're running, and proceed
while (someMethod2Invocations > 0)
wait();
someMethod1Invocations++;
}
// your code here
synchronized (this) {
// We're done with this method, so decrement someMethod1Invocations
// and wake up any threads that were waiting for that to hit 0.
someMethod1Invocations--;
notifyAll();
}
}
public void someMethod2() {
// comments are all ditto the above
synchronized(this) {
while (someMethod1Invocations > 0)
wait();
someMethod2Invocations++;
}
// your code here
synchronized(this) {
someMethod2Invocations--;
notifyAll();
}
}
One glaring problem with the above is that it can lead to thread starvation. For instance, someMethod1() is running (and blocking someMethod2()s), and just as it's about to finish, another thread comes along and invokes someMethod1(). That proceeds just fine, and just as it finishes another thread starts someMethod1(), and so on. In this scenario, someMethod2() will never get a chance to run. That's actually not directly a bug in the above code; it's a problem with your very design needs, one which a good solution should actively work to solve. I think a fair AbstractQueuedSynchronizer could do the trick, though that is an exercise left to the reader. :)
Finally, I can't resist but to interject an opinion: given that ConcurrentHashMap operations are pretty darn quick, you could be better off just putting a single mutex around both methods and just being done with it. So yes, threads will have to queue up to invoke someMethod1(), but each thread will finish its turn (and thus let other threads proceed) extremely quickly. It shouldn't be a problem.
I think this should work
class A {
Lock lock = new Lock();
private static class Lock {
int m1;
int m2;
}
public void someMethod1() throws InterruptedException {
synchronized (lock) {
while (lock.m2 > 0) {
lock.wait();
}
lock.m1++;
}
// someMethod1 and someMethod2 cannot be here simultaneously
synchronized (lock) {
lock.m1--;
lock.notifyAll();
}
}
public void someMethod2() throws InterruptedException {
synchronized (lock) {
while (lock.m1 > 0) {
lock.wait();
}
lock.m2++;
}
// someMethod1 and someMethod2 cannot be here simultaneously
synchronized (lock) {
lock.m2--;
lock.notifyAll();
}
}
}
This probably can't work (see comments) - leaving it for information.
One way would be to use Semaphores:
one semaphore sem1, with one permit, linked to method1
one semaphore sem2, with one permit, linked to method2
when entering method1, try to acquire sem2's permit, and if available release it immediately.
See this post for an implementation example.
Note: in your code, even if ConcurrentMap is thread safe, operation 1 and operation 2 (for example) are not atomic - so it is possible in your scenario to have the following interleaving:
Thread 1 runs operation 1
Thread 2 runs operation 1
Thread 2 runs operation 2
Thread 1 runs operation 2
First of all : Your map is thread safe as its ConcurrentMap. This means that operations on this map like add,contains etc are thread safe.
Secondaly
This doesn't guarantee that even your methods (somemethod1 and somemethod2) are also thread safe. So your methods are not mutually exclusive and two threads at same time can access them.
Now you want these to be mutex of each other : One approach could be put all operations (operaton 1,..operation 4) in a single method and based on condition call each.
I think you cannot do this without a custom synchronizer. I've whipped up this, I called it TrafficLight since it allows threads with a particular state to pass while halting others, until it changes state:
public class TrafficLight<T> {
private final int maxSequence;
private final ReentrantLock lock = new ReentrantLock(true);
private final Condition allClear = lock.newCondition();
private int registered;
private int leftInSequence;
private T openState;
public TrafficLight(int maxSequence) {
this.maxSequence = maxSequence;
}
public void acquire(T state) throws InterruptedException {
lock.lock();
try {
while ((this.openState != null && !this.openState.equals(state)) || leftInSequence == maxSequence) {
allClear.await();
}
if (this.openState == null) {
this.openState = state;
}
registered++;
leftInSequence++;
} finally {
lock.unlock();
}
}
public void release() {
lock.lock();
try {
registered--;
if (registered == 0) {
openState = null;
leftInSequence = 0;
allClear.signalAll();
}
} finally {
lock.unlock();
}
}
}
acquire() will block if another state is active, until it becomes inactive.
The maxSequence is there to help prevent thread starvation, allowing only a maximum number of threads to pass in sequence (then they'll have to queue like the others). You could make a variant that uses a time window instead.
For your problem someMethod1() and someMethod2() would call acquire() with a different state each at the start, and release() at the end.
I have a java applet. A class inside that applet is creating a thread to do some work, waiting 30 seconds for that work to complete, if its not completed in 30 secs it sets a Boolean to stop the thread. The wait and Boolean change are in a synchronized block, Is this necessary considering there is no other thread running aside from these 2.
System.out.println("Begin Start Session");
_sessionThread = new SessionThread();
_sessionThread.start();
synchronized (_sessionThread)
{
_sessionThread.wait(30000);
_sessionThread._stopStartSession = true;
}
Why couldn't I just do this instead.
System.out.println("Begin Start Session");
_sessionThread = new SessionThread();
_sessionThread.start();
_sessionThread.wait(30000);
_sessionThread._stopStartSession = true;
SessionThread run method. Invokes a JNI method to call a dll to open a program window.
public void run()
{
try
{
startExtraSession();
}
catch (Throwable t)
{
t.printStackTrace();
}
notify();
}
private native void openSessionWindow(String session_file);
private void startExtraSession()
{
final String method_name = "startExtraSession";
String title = _sessionInfo._title;
long hwnd = 0;
openSessionWindow(_sessionInfo._configFile);
try
{
//Look for a window with the predefined title name...
while ((hwnd = nativeFindWindow(title)) == 0 && !_stopStartSession)
{
Thread.sleep(500);
}
}
catch(Throwable t)
{
t.printStackTrace();
}
}
1. Is the synchronized really needed?
2. Is there a better way to accomplish this aside from using threads?
A given thread is required to own a lock on a object to be able to call wait(long) on it. This is achieved by using a synchronized block on the said object.
See J2SE specification on using wait.
Acquiring a lock/monitor in java can be done in various ways:
In a synchronized (non-static) method, the thread owns a monitor on the object referenced by this.
In a static synchronized method, the thread owns a monitor on the Class<?> descriptor for the class that defines the said method.
In a synchronized(x) block, the thread owns a monitor on x.
That lock will be released if:
You get outside of the synchronized code block (be it a method, static method, or explicit block).
You have called wait() or one of its variations (and you'll re-acquire it just before the method returns).
Both these two lists may omit specific cases but should cover at least a large portion of the typical use cases.
There's a very simple reason that you need synchronized to call wait
The synchronized makes sure that nobody is calling notify or notifyAll at the same time you're calling wait
For example: Thread 1
synchronized( obj )
{
triggerActionOnThread2();
obj.wait();
}
Thread 2 (triggered by triggerActionOnThread2)
...
synchronized( obj )
{
obj.notify();
}
If you don't have the synchronized blocks, then the notify might happen before (or during) the wait, and then the wait misses the notify, and you can hang Thread 1.
Imagine the above blocks of code without the synchronized blocks, and imagine if Thread 2 is executed all the way through the notify before the wait gets called.
BTW, I ask this very question on interviews for Java engineers when the job will involve multithreaded programming.
Can you please post SessionThread code? You cannot wait if you don't own the lock, so you need synchronized (_sessionThread) to do _sessionThread.wait(30000); Not sure what's with _sessionThread._stopStartSession = true;
If the boolean is the only shared state between the threads, declaring the boolean transient will guarantee that changes to it are seen between the threads as would a synchronization block around access to the boolean.