I know that the synchronize(LOCK) is unfair, which means there is no guarantee that the longest waiting thread will win the lock. However in my little experiment below it seems that the lock was acquired by shortest waiting threads...
public class Demo {
public static final Object LOCK = new Object();
public void unfairDemo(){
// Occupy the lock for 2 sec
new Thread(() -> {
synchronized (LOCK) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
// Spawn 10 new threads, each with 100ms interval, to see which can win the lock
// If lock is fair then it should print the i in asc order
for (var i = 0; i < 10; i++) {
int finalI = i;
new Thread(() -> {
System.out.println("Added " + String.valueOf(finalI) + "th element to wait for lock");
synchronized (LOCK) {
System.out.println("I got the lock, says " + String.valueOf(finalI) + "-th thread");
}
}).start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
// Keep the program alive
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Running unfairDemo() prints the following:
Added 0th element to wait for lock
Added 1th element to wait for lock
Added 2th element to wait for lock
Added 3th element to wait for lock
Added 4th element to wait for lock
Added 5th element to wait for lock
Added 6th element to wait for lock
Added 7th element to wait for lock
Added 8th element to wait for lock
Added 9th element to wait for lock
I got the lock, says 9-th thread
I got the lock, says 8-th thread
I got the lock, says 7-th thread
I got the lock, says 6-th thread
I got the lock, says 5-th thread
I got the lock, says 4-th thread
I got the lock, says 3-th thread
I got the lock, says 2-th thread
I got the lock, says 1-th thread
I got the lock, says 0-th thread
I expected that the order would be scrambled, but no matter how I tried the results are in reverse order. What did I do wrong here?
There are many sources, such as this, that already indicate that there should be no assumption regarding the order in which threads acquire locks. But it doesn't mean the order has to be scrambled.
It probably depends at the very least on the JVM implementation. For example, this document about HotSpot says:
Contended synchronization operations use advanced adaptive spinning techniques to improve throughput even for applications with significant amounts of lock contention. As a result, synchronization performance becomes so fast that it is not a significant performance issue for the vast majority of real-world programs.
...
In the normal case when there's no contention, the synchronization operation will be completed entirely in the fast-path. If, however, we need to block or wake a thread (in monitorenter or monitorexit, respectively), the fast-path code will call into the slow-path. The slow-path implementation is in native C++ code while the fast-path is emitted by the JITs.
I'm not an expert on HotSpot (maybe someone else can provide a more authoritative answer), but based on the C++ code, it looks like the contending threads will be pushed onto a LIFO structure, which may explain the stack-like order you observed:
// * Contending threads "push" themselves onto the cxq with CAS
// and then spin/park.
...
// Cxq points to the set of Recently Arrived Threads attempting entry.
// Because we push threads onto _cxq with CAS, the RATs must take the form of
// a singly-linked LIFO.
What did I do wrong here?
You do all right.
Your expirement shows program execution order in this particular case. Java do not guarantee any order of threads execution without special efforts from programmer's side.
Try this to see chaos:
public class Demo {
public static final Object LOCK = new Object();
public void unfairDemo() {
createThread(0).start();
for (var i = 1; i < 5; i++) {
createThread(i).start();
}
}
private static Thread createThread(final int number) {
return new Thread(() -> {
System.out.println("Added " + number + "th element to wait for lock");
synchronized (LOCK) {
System.out.println("I got the lock, says " + number + "-th thread");
try {
Thread.sleep(number == 0 ? 2000 : 100);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
});
}
public static void main(String[] args) {
new Demo().unfairDemo();
}
}
Related
I am trying to implement Reentrant locks on multi-threads but for some reason, the same thread unlocks and then locks again resulting in always the same thread to run therefore the same operation.
Below is the code how the threads are spawn
IntStream.range(0,(NUMBER_OF_THREADS)).forEach(index ->{
boolean operation = (index % 2 == 0) ? true : false;
Thread t = new Thread(new Client(operation,this));
t.start();
});
and here is how the run function of the thread works
#Override
public void run() {
while(!Thread.interrupted()) {
System.out.println("Trying to acquire lock : " + main.getLock().tryLock()
+ " thread id " + Thread.currentThread().getName());
// if (main.getLock().tryLock()) {
try {
main.getLock().lock();
if(main.getLock().isHeldByCurrentThread()) {
System.out.println("Lock held by this thread " + main.getLock().isHeldByCurrentThread()
+ " thread id : " + Thread.currentThread().getName());
if (operation) {
main.getcAaccount().deposit(1);
} else {
main.getcAaccount().withdraw(2);
}
Thread.currentThread().sleep(3000);
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("Thread id : " + Thread.currentThread().getName() + " unlocking");
main.getLock().unlock();//always have the unlock part here to ensure it unlock
}
}
It correctly prints that the other 5 threads are trying to acquire the lock and failing and then Thread id...is unlocking...and immediately the same thread locks again even though it should be sleeping.
Have I missed anything in this logic scenario?
Thank you in advance.
EDIT Screenshot of the suggested fix.
Reentrancy requires each lock to be followed by a subsequent unlock. For example, if I invoke lock.lock() three times, it's expected that I also invoke lock.unlock() three times. The ReentrantLock will not consider itself unlocked until this sequence of events occurs.
What you don't realize is that lock.tryLock(), if successful, will act essentially like invoking lock.lock(). So by locking twice, you need to also unlock twice. In your code example, you are unlocking only once and so the thread that initially locked still technically owns the lock.
Fixing it should be simple, you can remove the second lock.lock() from your code and the mutual exclusion should still hold. Either that, or if you need blocking on lock, then replace lock.tryLock() with lock.lock().
Based on your edit, you fixed one issue with removing the extra lock, but now you are running into a timing issue. You don't really need the tryLock. You can replace it with lock since a lock invocation will suspend the thread and block if the lock is already being held (eventually waking up when an unlock is invoked).
all. I have a question for Java wait-notify mechanism. The answer is is there a guaranty that the threads will be executed in this order - from last to the first etc. the result always will be 100, 99, ... , 1 ? This is the snippet of code:
public class Main {
static int counter = 0;
static Object o = new Object();
public static void main(String[] args){
for(int i = 0; i < 100; ++i){
new Thread(() -> {
synchronized (o) {
try {
int c = ++counter;
o.wait();
System.out.println("" + c);
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (o) {
new Thread(()-> {
synchronized(o){
System.out.println("LAsttttttttttttttttt");
}
}).start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
o.notifyAll();
}
}
}
I run it 10 times and the result is always the same. I coudn't find anything about this in internet. And one more question - when we have 100 threads waiting, when we notifyAll, is there a guaranty that first one of waiting threads will be executed, after then a second one and after all 100 waiting threads are executed, other waiting methods(which were in synchronized block, but don't have wait() in their body), will be executed after that (after all 100 threads that were waiting are executed). Or notifyAll only guaranty that all waiting threads will start fighting with every method which is synchronized by this object? I thing that this is the answer :
"The awakened threads will not be able to proceed until the current
* thread relinquishes the lock on this object. The awakened threads
* will compete in the usual manner with any other threads that might
* be actively competing to synchronize on this object; for example,
* the awakened threads enjoy no reliable privilege or disadvantage in
* being the next thread to lock this object."
But I want to be sure that I understand what's going on when we have wait-notify.
Thanks in advance.
No . .there is no guarantee that a set of awoken threads will be executed in any particular order. (This may happen in order because of a particular implementation of JVM or the speed of the computer the program is run on, or many other load based variables. However, there is no language guarantee.)
Java's synchronized code block makes no guarantee about the sequence in which threads waiting to enter the synchronized block are allowed to enter, and notifyAll() doesn't present itself as a special case.
As you have seen in notifyAll() javadoc (emphasis mine):
The awakened threads will not be able to proceed until the current thread relinquishes the lock on this object. The awakened threads will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened threads enjoy no reliable privilege or disadvantage in being the next thread to lock this object.
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.
I just started out with threading. I wrote a main class that sets up and starts 100 threads, waits 5 seconds and then interrupts them (at least that's what I thought it did):
public static void main(String[] args) {
List<Thread> threads = new ArrayList<Thread>();
for (int i = 0; i < 100; i++) {
Thread t = new Thread(new Walker());
threads.add(t);
}
System.out.println("Starting threads...");
for (Thread thread : threads) {
thread.start();
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// don't do anything
}
System.out.println("Time's up - Terminating threads...");
for (Thread t : threads) {
t.interrupt();
System.out.print(".");
}
for (Thread t : threads) {
try {
t.join(10);
} catch (InterruptedException e) {
// don't do anything
}
}
System.out.println("");
System.out.println("All done.");
}
The threads looked a bit like this:
public class Walker implements Runnable {
public void run() {
for (int i = 0;; i++) {
//do some complicated stuff that takes some time
System.out.println(Thread.currentThread().getName() + ":" + i);
if (Thread.interrupted()) {
break;
}
}
}
}
Now, the output I got was that the main thread began interrupting threads, but some sub threads continued to run a few times (i.e. loop iterations) before terminating, e.g.
Starting threads...
Thread-1:0
Thread-2:0
Thread-1:1
Thread-3:0
[...]
Time's up - Terminating threads...
......Thread-1:60
Thread-1:61
...Thread-1:62
Thread-2:55
..All done.
[output from threads sometimes continued even here - after the join()]
At that time I didn't fully understand that a single thread could be allocated enough processor time to run a few times - I expected at most one additional run before the main thread had the opportunity to interrupt it.
But while I now see that it is absolutely fine for a thread to be executed for some (long) time before the main thread gets a chance to terminate (i.e. interrupt) it, I am still wondering: is there an easy way to interrupt all child threads in a timely manner from the main thread? (Setting a "time to live" through a thread's constructor and then testing inside the Walker class for it is not what I want.)
Also: is it possible for the last print statement to execute and then see some output from individual threads - after all threads were join()ed? (Maybe I have a glitch somewhere else; the actual code is a bit more complex...)
The problem you observe is probably due to how System.out.println works. It is a synchronized method. So a likely explanation is:
when calling System.out.print("."); after t.interrupt();, your main thread acquires the lock to print
before the lock is released, worker threads arrive at System.out.println(Thread.currentThread().getName() + ":" + i); and wait for the lock
when the main thread releases the lock, all the worker threads that were waiting print their progress.
the main thread arrives at System.out.print("."); again and has to wait for the print lock to be available, etc.
Regarding the fact that you see more prints from the worker threads after "All Done" is printed: you only join for 10 ms, so it is possible that it is not enough and a thread is not finished within 10ms of being interrupted. If you just use join() you should not see that any longer.
Example of Worker class that reproduces the behaviour you observe:
class Walker implements Runnable {
public void run() {
for (int i = 0;; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
//do not respond to interruption too quickly on purpose
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
Thread.currentThread().interrupt();
}
System.out.println(Thread.currentThread().getName() + ":" + i);
if (Thread.interrupted()) {
break;
}
}
}
}
It would be easier with ExecutorService, eg
int nThreads = 100;
ExecutorService ex = Executors.newFixedThreadPool(nThreads);
for (int i = 0; i < nThreads; i++) {
ex.execute(new Walker());
}
Thread.sleep(5000);
ex.shutdownNow();
Maybe I have a glitch somewhere else; the actual code is a bit more complex...
Yes it is a glitch, unfortunately isn't a simple set 1 property, java side.
If the code is commercial, complex, than you can allocate a bit more time to write some native libraries, for major Os type. With that help you can easily play with threads as you wanted.
The first times has an overhead for developing and understanding how the threads are woking in native, os side, than just call a function with a few params :)
Not sure, if is helping, the glitch exists.
I was going through threads and I read that ..The notify() method is used to send a signal to one and only one of the threads that are waiting in that same object's waiting pool.
The method notifyAll() works in the same way as notify(), only it sends the signal to all of the threads waiting on the object.
Now my query is that if Lets say I have 5 threads waiting and through Notify() , i want to send to notification to thread 3 only, what logic should be there that notification is sent to thread 3 only ..!!
You can't directly do this with wait and notify. You'd have to set a flag somewhere, have the code in the thread check it and go back to waiting if it's the wrong thread, and then call notifyAll.
Note that if you have to deal with this, it might be a sign that you should restructure your code. If you need to be able to notify each individual thread, you should probably make each of them wait on a different object.
wait-notify is rather a low level mechanism to indicate to other threads that an event (being expected occured). Example of this is producer/consumer mechanism.
It is not a mechanism for threads to communicate to each other.
If you need something like that you are looking in the wrong way.
The following code starts up five threads and sets the third one a flag which tells it that it is the only to continue. Then all of the threads that are waiting on the same lock object lock are notified (woken-up), but only the one selected continues. Be careful, writing multi-threaded applications is not easy at all (proper synchronization, handling the spurious wake-ups, etc.) You should not need to wake up only one particular thread from the group as this points to an incorrect problem decomposition. Anyway, here you go...
package test;
public class Main {
public static void main(String[] args) {
Main m = new Main();
m.start(5);
}
private void start(int n) {
MyThread[] threads = new MyThread[n];
for (int i = 0; i < n; i++) {
threads[i] = new MyThread();
/* set the threads as daemon ones, so that JVM could exit while they are still running */
threads[i].setDaemon(true);
threads[i].start();
}
/* wait for the threads to start */
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
/* tell only the third thread that it is able to continue */
threads[2].setCanContinue(true);
/* wake up all threads waiting on the 'lock', but only one of them is instructed to continue */
synchronized (lock) {
lock.notifyAll();
}
/* wait some time before exiting, thread two should be able to finish correctly, the others will be discarded with the end of the JVM */
for (int i = 0; i < n; i++) {
try {
threads[i].join(500);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
System.out.println("Done!");
}
/** synchronization object, i.e. a lock which makes sure that only one thread can get into "Critical Section" */
private final Object lock = new Object();
/** A simple thread to demonstrate the issue */
private final class MyThread extends Thread {
private volatile boolean canContinue;
#Override
public void run() {
System.out.println(Thread.currentThread().getName() + " going to wait...");
synchronized (lock) {
while (!canContinue) {
try {
lock.wait(1000); /* one second */
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
System.out.println(Thread.currentThread().getName() + " woken up!");
}
public void setCanContinue(boolean canContinue) {
this.canContinue = canContinue;
}
};
}
The output of the code is:
Thread-0 going to wait...
Thread-2 going to wait...
Thread-3 going to wait...
Thread-1 going to wait...
Thread-4 going to wait...
Thread-2 woken up!
Done!
So you can clearly see that only the third thread (indexed from zero) is woken up. You have to study the Java synchronization and multi-threading in more detail to understand every particular line of the code (for example, here).
I would like to help you more, but I would have to write almost a book about Java threads and that is why I just pointed out to this Java Tutorial on threads. You are right, this problematics is not easy at all, especially for beginners. So I advise you to read through the referenced tutorial and then you should be able to understand most of the code above. There is no easy way around or at least I do not know of any.