As shown in the code, locksupport.park () is called twice in thread t1. After LockSupport.park () for the first time, the main Thread wakes up Thread t1 with t1.interrupt() and then calls thread.interrupted () in t1 to clear the interrupted status of the thread. But Locksupport.park () does not suspend the thread a second time. Oddly enough, After comment out the [log.debug("test.......")], locksupport.park () can pause the thread a second time. What is the reason for this?
enter image description here
enter image description here
#Slf4j
public class Test08Park4 {
public static void main(String[] args) throws InterruptedException{
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
LockSupport.park();
/**
* With this log print, locksupport.park () cannot stop threads;
* If you comment this out, locksupport.park () can stop the thread
*/
log.debug("test.......");
Thread.interrupted();
LockSupport.park();
log.debug("finished...");
}
});
t1.start();
sleep(1000);
t1.interrupt();
}
}
if do not comment [log.debug("test.......")] out,the result:
22:37:05.435 [Thread-0] DEBUG test.Test08Park4 - test.......
22:37:05.439 [Thread-0] DEBUG test.Test08Park4 - finished...
if comment [log.debug("test.......")] out,the result:
//nothing
Reading docs is fundamental.
As the docs indicate, LockSupport.park() is allowed to spuriously return. In other words, the docs literally spell out:
Q: "Why did the park() call return so quickly?"
A: Because the JVM felt like it.
LockSupport's locks are thread-global. There is exactly one semaphore (which LockSupport calls a 'permit') for each thread, you can't make more and you can't make less. Basically meaning, exactly one system within your JVM can use it, because if two use it, they confuse each other.
As the docs also say:
Basic thread blocking primitives for creating locks and other synchronization classes.
Which in essence means: Why are you doing this? If you want locking behaviour, use e.g. ReentrantLock from the java.util.concurrent package; this isn't meant for you, and hence it has all sorts of bizarre weirdness in it, such as park()'s rule that it is allowed spurious returns.
Most likely the log.debug code either [A] ends up calling LockSupport.unpark(ownThread) for some reason, which means the next park() call returns immediately, or [B] it's a timing matter. log.debug is not 'free', many log frameworks run 'in-place', meaning, the log.debug call actually goes out on disk and fsyncs, meaning, it takes a very long time indeed compared to your average non-disk-interacting java instruction (hundreds of instructions worth of time). That time is enough for the scheduler to fly by it, especially considering 'write to disk' or 'fsync' is a natural stopping point (threads in java are pre-emptive, but if you give the scheduler an excuse to pause your thread, it will usually take it).
In the end, the docs are clear: You don't get an answer to your 'why' question. The specs give the JVM free reign not to have to explain to you why park() spuriously returns. Therefore there isn't much point chasing down the why for this case - even if you have an answer, tomorrow there can be a different reason. If your code can't handle spurious returns on LockSupport.park(), your code is by definition broken. Even if you can make it work on your machine, today, with this phase of the moon, then that's no guarantee it would work fine tomorrow.
Once your code can handle spurious returns, figuring out why it spuriously returns here isn't interesting anymore. Thus, solution: Deal with spurious returns properly. Or, more likely, don't use this for locks, use something more friendly to end users.
Related
I was reading about ways to end a thread in https://docs.oracle.com/javase/7/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html, which is a link I found from the question How do you kill a thread in Java?
In the first link, they first discuss using a volatile variable to signal to the thread that you want to terminate. The thread is supposed to check this variable and cease operation if the variable has a value that means cease (e.g. if it is null). So to terminate the thread, you would set that variable to null.
Then they discuss adding interrupts to help with threads that block for long periods of time. They give the following example of a stop() method that sets the volatile variable (waiter) to null and then ALSO throws an interrupt.
public void stop() {
Thread moribund = waiter;
waiter = null;
moribund.interrupt();
}
I am just wondering, why would you need both? Why not ONLY use interrupt(), and then handle it properly? It seems redundant to me.
(First part of this is in general, arguably I was not paying attention to the specifics of the question. Skip to the end for the part that addresses the techspec discussed in the question.)
There is no good technical reason. This is partly about human limitations and partly about confusing api design.
First consider application developers’ priority is creating working code that solves business problems. Thoroughly learning low level apis like this gets lost in the rush to get work done.
Second there’s a tendency when you’re learning things to get to a good enough state and leave it there. Things like threading and exception handling are back-of-the-book topics that get neglected. Interruption is a back of the book topic for threading books.
Now imagine a codebase worked on by multiple people with varying skill level and attention to detail, who may forget that throwing InterruptedException from wait and sleep resets the interrupt flag, or that interrupted isn’t the same as isInterrupted, or that InterruptedIoException resets the interrupt flag too. If you have a finally block that catches IOException, you may miss that InterruptedException is a subclass of IOException and you could be missing out on restoring the interrupt flag. Probably people in a hurry decided to hell with it, I can’t count on this interrupted flag
Is it right? No.
The hand rolled flag doesn’t help with short circuiting wait or sleep the way interruption does.
the Java 5 concurrency tools expect tasks to use interruption for cancellation. Executors expect tasks submitted to them to check for interruption in order to quit gracefully. Your tasks may use other components, like a blocking queue. That queue needs to be able to respond to interruption, the thing using it needs to be aware of the interruption. The handrolled flag doesn’t work for this since the java 5 classes can’t know about it.
Having to use interruption because you’re using tools that expect it, but not having confidence in the flag value due to unmanageable technicalities, would lead to this kind of code.
(end of rant, now actually responding to the specific techspec example)
OK, looking at this techguide article in particular. Three things stand out:
1) it's not making use of interruption at all, except to cut the sleep time short. Then it just squelches the exception, and doesn't bother to restore the flag or check it. You could use the InterruptedException to terminate by catching it outside the while loop, but that's not what this does. This seems like a strange way to do this.
2) as the example is fleshed out it becomes clear the flag is being used to turn the waiting on and off. Somebody might use interruption for this but it's not idiomatic. So having a flag is ok here.
3) this is a toy example in a techguide. Not all the Oracle content is as authoritative as the techspecs or the API documentation. Some tutorials have misstatements or are incomplete. It might be the reason the code was written like this was that the author figured readers would not be familiar with how interruption worked and it was better to minimize its usage. Technical writers have been known to make choices like that.
If I rewrote this to use interruption I would still keep the flag; I'd use interrupt to terminate, and use the flag for suspend/resume functionality.
Please see this documentation.
Your thread should check thread.isInterrupted() status, for example:
Thread myThread = new Thread() {
#Override
public void run() {
while (!this.isInterrupted()) {
System.out.println("I'm working");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
//We would like also exit from the thread
return;
}
}
}
};
And when you would like to stop the thread, you should invoke
myThread.interrupt();
Besides we can use static method Thread.interrupted() that also checks the status but after that, the method clears it and you have to invoke again myThread.interrupt() to set the status again. But I don't recommend to use Thread.interrupted() method.
This approach helps gracefully stop the thread.
So I also do not see any reasons to use an additional volatile variable.
The same behavior can be reached via additional volatile flag as in #lexicore's answer, but I think it is redundant code.
#NathanHughes is completely right, but I am going to rephrase his long answer into few words: third-party code.
This is not just about "dumb junior developers", — at some point in application's life you will be using lots of third-party libraries. Those libraries will not gentlemanly respect your assumptions about concurrency. Sometimes they will silently reset interruption flag. Using separate flag solves that.
No, you can not get rid of third-party code and call it a day.
Suppose, that you are writing a library, — for example, ThreadPoolExecutor. Some of the code inside your library needs to handle interruption… Or even unconditionally reset the interruption flag. Why? Because previous Runnable is done, and a new Runnable is on the way. Unfortunately, at that point there may be a stale interruption flag, that was aimed… wait, whom was it for again? It could have been addressed for previous Runnable or for new (not yet running) Runnable, — there is no way to tell. And this is why you add isCancelled method to FutureTask. And unconditionally reset interruption flag before executing new Runnable. Sounds familiar?
Thread#interrupt is completely detached from the actual work units, running on that thread, so adding an additional flag is necessary. And once you have started doing so, you have to do that all the way — up to the outermost and down to the innermost work unit. In effect, running unknown user-supplied code on your threads makes Thread#interrupted unreliable (even if Thread#interrupt still works fine!)
I got two threads: A and B.
There is an endless loop in thread A:
while ( true ) {
// Do something
}
Thread B is monitoring some state of interest to me. When the state changes, I want thread A to stop any further execution.
The following solution is not sufficient (setting keepRunning to true with method in A which is called from B):
while ( keepRunning) {
// Do something
}
I can't wait for the body of the loop to be executed before thread A is halted - I want the execution of the methods called in the loop to be interrupted.
Is there a way to achieve the above functionality?
You can do a few point fixes, like checking keepRunning at key points in A's loop. You could also interrupt thread A, which only helps you if it calls any methods that throw InterruptedException.
But you can't just have thread A stop dead in its tracks, and for good reason: this would be prone to deadlock. There used to be a methods Thread.stop and Thread.suspend that did just that, and they've been deprecated because of those dangers. Starting in Java 8, that method throws UnsupportedOperationException.
Basically, a thread has to stop itself. It can do so at the request of other threads (communicated by a field like keepRunning or by an interrupt), but it has to do it. One thread can't directly stop another.
You can interrupt the Thread at any point, however this only triggers an InterruptedException in the method should check this.
You can attempt to stop a thread however, this is an unsafe operation as it can occur at any point and unless you are very careful, this can leave memory in an inconsistent state. If you are going to be that careful, you may as well add some checks and stop the code early.
This is a really bad idea, because what happens when there are critical resources open, like e.g. a file? It won't be closed:
while (keepRunning) {
openFile();
// gets stopped here
closeFile();
}
This can of course happen with other things as well, OS processes, network sockets, anything. You see why this is a bad idea?
You should instead redesign the code in the loop to check for the condition more often and break and cleanup if the condition doesn't hold true anymore.
while (keepRunning) {
openFile();
doLongOperation();
if (!keepRunning) {
closeFile();
break; // or return
}
doAnotherLongOperation();
closeFile();
}
This way, you don't lose the safety, while being able to stop it faster.
You might not actually use precious resources, but in any case you should tell us more details so we can give a more precise answer.
So basically I am learning a bit more serious concurrency (studying how things actually work, instead of just using random stuff if needed).
And my proffesor, when I asked him about this, said me that he and his colleagues hadn't been able to reproduce a spurious wake up, and believes that line is an old line not deleted (like, it was there, java got "better", it's not longer needed, the line is still there), and that is not the case.
Link:
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Condition.html
It's right below the point called:
Implementation Considerations
In his opinion, a condition that looked kind of like this:
lock.lock()
if (p>q) {
lock.newCondition().await
}
Would be perfectly fine, since he says a spurious wake up can not happen, it wouldn't be needed a loop:
lock.lock()
while (p>q) {
lock.newCondition().await
}
I am MORE than likely mixing things and understanding both the doc and my teacher the wrong way, but I do have spent some time trying to understand why each thing, and can't come with an "answer" of my own, I either believe one or the other (not like it matters, it's pure I-want-to-learn).
My teacher does spend time telling us how explaining concurrency in java it's pretty silly, but I didn't choose it either, so there's that.
Would be perfectly fine, since he says a spurious wake up can not happen, it wouldnt be needed a loop:
Your teacher is wrong for two reasons:
Spurious wakeups do happen. It may not happen on the architecture that they tested on but if you don't take it into account, when you move your application to a different piece of hardware or a different OS revision, you will see problems. It may also be that the spurious interrupts happen occasionally during an exceptional kernel event such as a signal getting delivered at precisely the wrong time. Again, your application may run fine in testing but when you move it into production with a lot higher load, the frequency of the exceptional event may increase...
The underlying problem is that certain native thread implementations may choose to wakeup all conditions associated with an application instead of the specific one that was notified. This is well documented in the javadocs for Object.wait():
As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop:
Here's one example of an architecture that has this limitation. I'll quote from this interesting blog entry:
Internally, wait is implemented as a call to the 'futex' system call. Each blocking system call on Linux returns abruptly when the process receives a signal -- because calling signal handler from kernel call is tricky. What if the signal handler calls some other system function? And a new signal arrives? It's easy to run out of kernel stack for a process. Exactly because each system call can be interrupted, when glibc calls any blocking function, like 'read', it does it in a loop, and if 'read' returns EINTR, calls 'read' again.
The while loop is also very important to protect against race conditions -- especially in multiple thread producer/consumer models. If you have multiple threads that are consuming from a queue (for example), a notification that there are items in the queue may wakeup a thread but by the time it is able to get the lock, another thread has already dequeued the item.
This is well documented on my page here with a sample program that demonstrates the race condition without the use of while.
Producer Consumer Thread Race Conditions
In your example, thread A may be waiting in await() while another thread B may be waiting to get the lock(). Thread C has the lock and is adding to the queue.
// B is here waiting for the lock
lock.lock()
while (p > q) {
// A is here waiting for the signal
lock.newCondition().await();
}
// dequeue
lock.unlock();
Then if the producer adds something to the queue and calls signal() the thread A moves from the WAIT state to the BLOCKED state to get the lock itself. But it may be behind thread B which is already waiting. Once the lock is released, thread B dequeues the element, not thread A. When thread A then gets a chance to dequeue, the queue is empty. Without the while loop, you can get out-of-bounds exceptions or other problems by trying to dequeue from an empty queue.
See my link for more explicit details of the race.
It is still necessary. Your professor is not necessarily incorrect, but has created a strawman argument to knock down.
There are two reasons why you must protect your conditions in a loop.
The first is spurious wake-up. Your professor seems to have been unable to reproduce this, and it may likely not be a problem on the platforms he tests on. This does not mean it is unreproduceable on all platforms.
The second is that between the times that you wake up and actually go to do the logic, the condition may no longer be true. You must guard against this potential race condition. This is also notoriously difficult to reproduce in the lab, and will probably only happen in bizarre circumstances in production.
I realized that this code:
public class TestThread3 extends Thread {
private int i;
public void run() {
i++;
}
public static void main(String[] args) {
TestThread3 a = new TestThread3();
a.run();
System.out.println(a.i);
a.start();
System.out.println(a.i);
}
}
results in 1 1 printed ... and i don't get it. I haven´t found information about how to explain this. Thanks.
results in 1 1 printed
So the first a.run(); is called by the main-thread directly by calling the a.run() method. This increments a.i to be 1. The call to a.start(); then is called which actually forks a new thread. However, this takes time to do so the i++; operation most likely has not started before the System.out.println(...) call is made so a.i is still only 1. Even if the i++ has completed in the a thread before the println is run, there is nothing that causes the a.i field to be synchronized between the a thread and the main-thread.
If you want to wait for the spawned thread to finish then you need to do a a.join(); call before the call to println. The join() method ensures that memory updates done in the a thread are visible to the thread calling join. Then the i++ update will be seen by the main-thread. You could also use an AtomicInteger instead of a int which wraps a volatile int and provides memory synchronization. However, without the join() there is still a race condition between the a thread doing the increment and the println.
// this provides memory synchronization with the internal volatile int
private AtomicInteger i;
...
public void run() {
i.incrementAndGet();
}
...
a.start();
// still a race condition here so probably need the join to wait for a to finish
a.join();
System.out.println(a.i.get());
This behavior can change at any point of time because when a.start() is called, the thread is scheduled for process, not necessary the OS will let it start executing on CPU.
Once a.start() returns, you actually have two threads (one is for main and another is a new thread), and the main would still be running.
The expected result could only come if following happens,
Time
T1 main method calls a.start()
T2 jvm / os schedules thread for execution
T3 a.start() returns and main thread gets context-switched and suspended for other threads.
T4 Spawned thread gets execution context, and its run method is called, which increments value
T5 context switch happens and main thread gets the control back
T6 main thread would print 2
Jatan
You have two main issues here to clear up. I also recommend you examine Gray's answer for more technical information.
**Note: This just skims the surface, but most of the other answers take for granted the background knowledge on these Computer Science topics that I believe you have not yet mastered.
First, threads are not guaranteed order of execution. In general, you should only use threads if they can work asynchronously (independently timed). For this example, you have a timing-specific expected outcome, so threading should probably just be avoided.
This, however, isn't your only issue.
As is, your code also has what is called a Race Condition. A Race Condition occurs when two different threads (or processes) have access to read/manipulate the same data -- In your case, reading i and incrementing via i++.
For example,
Imagine that you and a friend both have a dollar. The Ice Cream Man drives along and stops in front of you. The Ice Cream Man only has one ice cream cone left. There are a couple of ways this could play out:
You are faster than your friend and buy the cone first.
You are slower than your friend and he buys the cone first.
You decide to split the ice cream cone and both pay $0.50.
You two fight and someone else gets to buy the last ice cream cone while you two are distracted.
To mirror this back to the computer,
The main thread where you are printing continues to run even after you started the second thread. (Threads are linked to the same process, so when main returns, the other threads "die". It is possible the thread, even though it a.start()'ed, doesn't finish or may not even get a chance to run at all!)
The other thread gets to run and completes before returning to the main thread.
You take turns executing and everyone gets to do a few lines of code. The out come is really asynchronous here. And this can very likely happen.
The java application process loses the CPU and someone else gets to run (potentially accessing similar shared information.)
TL;DR -
If you want to ensure execution order, then just DO NOT use threads.
There are some cases where syncing up at certain points along the way would be nice. For these cases, you can join the threads (wait for one to finish before continuing), or lock the Race Condition with a Mutex or Semaphore (more advanced synchronization techniques).
I recommend doing some reading on these topics before attempting to jump into battle with the monstrous operating system.
In the below code the answer is always Started 0 1 2 3 Complete. Im just wondering how it is possible.
If someone could help with the consistency of the output, it would be nice
public class TestOne extends Thread {
/**
* #param args
*/
public static void main(String[] args)throws Exception {
// TODO Auto-generated method stub
Thread t = new Thread(new TestOne());
t.start();
System.out.println("started");
t.join();
System.out.println("Complete");
}
public void run(){
for(int i=0;i<4;i++){
System.out.println(i);
}
}
Most likely you're getting the same results because, most of the time, the main thread starts a new thread then, before that new thread has a chance to print anything, the main thread prints its started message. The join in the main thread then forces it to wait until the other thread has finished, then it prints Complete.
You have a race condition here. The instant you start the second thread, it's indeterministic as to which order the lines will be output (other than the complete line which is made deterministic by virtue of the wait call, as previously mentioned).
But a race condition doesn't guarantee that you'll get different results on multiple runs, only that it is possible. You still shouldn't rely on that behaviour, of course.
For example, the following code:
public class TestOne extends Thread {
public static void main (String[] args) throws Exception {
Thread t = new Thread (new TestOne());
t.start();
Thread.sleep (1000); // <- Added this.
System.out.println ("Started");
t.join();
System.out.println ("Complete");
}
public void run() {
for (int i = 0; i < 4; i++) {
System.out.println (i);
}
}
}
will output:
0
1
2
3
Started
Complete
Although, even then, the order is not guaranteed as it may take more than a second for the thread to "warm up" - sleep is rarely a good solution to race conditions. I've just used it here for illustrative purposes.
When you say Thread t = new Thread(); nothing special happens because you are not creating a "Thread" per se. It is just an object that has the "characteristics" to become a thread of execution. For the object to be a "Thread" you have to call t.start(); and this is where the magic lies.
When you say t.start() the JVM creates a new stack for the newly created thread to run. It associates that stack to the thread object in question. And then makes it available for scheduling. Basically this means that it queues the thread in the JVM scheduler and in the next time slice it is also available for execution. The JVM actually does a lot more than this, my answer is just oversimplified for your example.
Invariably, meanwhile all these thread + stack creation, your main thread has the opportunity to move to its next instruction which in your case is System.out.println("started");.
Theoretically, what you say is true, "Started" could come anywhere in between 0, 1, 2, 3. However in reality, since your t.start() is an "expensive" method, it takes some time to complete, during which the main thread generally gets the chance to execute its next instruction.
If you want to know the details of t.start(); look into the Java source code.
Clearly, you are seeing a consistent result (and this particular result) because on your machine the call to the child thread's run method is consistently happening after the println in the main thread.
Why is it consistent?
Well, simply because your platform's native thread library is behaving in a consistent fashion!
Typical modern Java virtual machine implementations use the host operating system's native thread support to implement Java threads, and to perform Java thread scheduling. On your machine, the native thread implementation appears to be consistently allowing the current thread to return from the Thread.start() call immediately and keep executing.
However, it is not guaranteed that this will always happen. For instance, if the machine was heavily loaded and the main thread had just about exhausted its current timeslice, it could get descheduled during or immediately after the start call, allowing the new thread to run first.
Furthermore, on another platform the normal scheduler behaviour could be different. The scheduler could consistently cause the current thread to deschedule and let the new one go first. Or it could happen "randomly".
The JVM and Java library specs deliberately do not specify which thread "goes first" precisely to allow for differences in the thread implementation ... and variation due to differences in hardware, system load and so on.
Bottom line - the apparent consistency you are seeing is an "artifact", and you shouldn't rely on it, especially if you want your application to work on a wide range of JVMs.
Simply put, the scheduling of the started thread with respect to the main thread is JVM implementation dependent. But that being said, most implementations, if not all, will leave the starting thread running to the completion of its timeslice, until it blocks on something, or until it is preempted by a higher priority thread (if preemptive scheduling is being used, also JVM implementation dependent).
The Java spec just does not say very much which is very specific about threading, deliberately to grant JVM writers the most scope for their implementation.
t.join() means "block until thread t has finished", which explains the "Completed" being last.
EDIT: In answer to question re "Started"...
The call to Thread.start() means "please schedule this thread to run", and it will start when java feels like starting it. The chance of that happening between t.start() the println() is platform dependant, but small on systems I've used (thx to # Stephen C for platform info).
This code however outputs 0, Started, 1, 2, 3, Completed:
Thread t = new Thread(new TestOne());
t.start();
try
{
Thread.sleep(100); // Added sleep between t.start() and println()
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("Started");
t.join();
System.out.println("Complete");
When you start a thread it takes time (nothing comes for free or occurs instantly)
The thread which is already running will almost always be quicker to print out than a thread which has just started.
If you really want to the order to be different every time you can use run() instead of start() This works because you only have one thread.