In the below code about the synchronisation between threads, according to the output generated why is the control being transferred to the execution of the new thread despite the lock being acquired for the same object "dt" in the main method ?
public class DemoThread extends Thread {
public DemoThread() {
}
public void run() {
int i=0;
synchronized(this) {
while(++i<=5) {
sum=i;
try{
sleep(1000);
System.out.println("Woke up from sleep");
if(i>=2) this.notify();
}catch(InterruptedException ie) {
ie.printStackTrace();
System.exit(1);
}
}
}
}
private static int sum;
public static void main(String... args) {
DemoThread dt = new DemoThread();
dt.start();
synchronized(dt) {
try{
System.out.println("main here");
dt.wait();
System.out.println("main here again");
System.out.println("sum = " + sum);
}catch(InterruptedException ie){
ie.printStackTrace();
System.exit(1);
}
}
}
}
Output :
main here
Woke up from sleep
Woke up from sleep
Woke up from sleep
Woke up from sleep
Woke up from sleep
main here again
sum = 5
EDIT: I think I was able to find one of the possible flow of the code to explain the output:
1.Main thread enters in the Sync block in the main method.
2.call to the wait is made. Lock released on the dt object
3.New thread enters the while loop as it has the lock on the object dt
4.Thread.Sleep is executed and it doesn't release the lock
5.notify call is made but doesnot wakr the main thread(?)
6.New and the main thread finish the execution
Please correct me if I am wrong
You are close :
1.Main thread enters in the Sync block in the main method.
2.call to the wait is made. Lock released on the dt object
3.New thread enters the while loop as it has the lock on the object dt
4.Thread.Sleep is executed and it doesn't release the lock
5.notify call is made but doesnot wake the main thread(?)
6.New and the main thread finish the execution
Until the step 4, it is correct.
Here is what it happens at the step 5 :
notify() is invoked and the main() thread is so notified.
But it will not have a chance to run again right now.
Why ? Because the DemoThread thread doesn't release the lock.
The notify() method is indeed executed in a loop inside a synchronized statement.
synchronized (this) {
while (++i <= 5) {
sum = i;
try {
sleep(1000);
System.out.println("Woke up from sleep");
if (i >= 2) {
notify();
}
} catch (InterruptedException ie) {
ie.printStackTrace();
System.exit(1);
}
}
And according to Object.notify() javadoc :
The awakened thread will not be able to proceed until the current
thread relinquishes the lock on this object. 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 the main() thread could run only as the run() method DemoThread is terminated.
To let the main() thread to run again, you could reverse in the DemonThread run() method, the synchronized statement and the while statement.
You should also make this thread sleep a little bit to let the main() thread to run again.
public void run() {
int i = 0;
while (++i <= 5) {
// let a chance for other threads
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (this) {
sum = i;
try {
sleep(1000);
System.out.println("Woke up from sleep");
if (i >= 2) {
notify();
}
} catch (InterruptedException ie) {
ie.printStackTrace();
System.exit(1);
}
}
}
}
Now as i >= 2, as previously, other threads are notified but as the thread leaves the lock as it loops on the while and then sleep 100 ms, the main() thread can run again.
Here is the output :
main here
Woke up from sleep
Woke up from sleep
main here again
sum = 2
Woke up from sleep
Woke up from sleep
Woke up from sleep
The synchronized keyword isn't used to control the execution of a thread, it's used to ensure that only one thread can enter a block of code at any one time.
Typically whole methods can be synchronized or code between {}.
You can also synchronize an object that will be shared between two or more threads, typically some data structure that will be updated by the threads and you need to ensure that the state is consistent and not partially updated.
In your example there is no contention on the synchronize, if you extedt the sample to introduce some object and multiple threads trying to write and read from this object you will get a better understanding.
Related
I'm having trouble getting over 100 threads to run simultaneously. When I do a thread dump, I noticed that many of them are in parked status, i.e.
parking to wait for <0x00000000827e1760> (java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject).
The program runs fine with about 25 threads or less. Is there a way ti identify what's causing the concurrent lock, and/or prevent it? This was running in a fixed pool size of 200 using the Executor service.
Apologies for the lack of code - it's proprietary and there's a lot to be changed to obfuscated it.
Are you using some sort of ThreadPoolExecutor such as the ones provided by java.util.concurrent.Executors class? Perhaps you are facing a case of tasks being finished by silently uncaught exceptions. The dump fragment looks like an inactive pooled thread and one reason to get an inactive thread (which should be active) is an exception throwed up but surrounded by the default thread pool implementation.
LockSupport.park()
In thread pools, THREADS waiting for a TASK are locked out by LockSupport.park();. See java.util.concurrent.locks.AbstractQueuedSynchronizer source from openjdk :
public final void await() throws InterruptedException {
// code omitted
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
// code omitted
}
It means that the TASK which the THREAD were executing finished (abruptaly or not) and now the thread is waiting for another task to execute (see java.util.concurrent.ThreadPoolExecutor openjdk source):
private Runnable getTask() {
// ...
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take(); <== the thread is blocked here
// ...
}
As one can see, the thread is locked out in the call workQueue.take();.
Thus, shortly, threads in "parked status" are just waiting for new tasks after the previous ones have finished.
Why does my task is no longer running?
The most reasonable cause of a finished task is the regular end of the run(). The task flow finishes and then the task is released by the respective owner thread. Once the thread releases the task, it is ready to execute another task as long there is one.
A straightforward way to check this scenario is by logging something in the end of the run() method:
class MyRunnable implements Runnable {
public void run() {
while(/*some condition*/) {
// do my things
}
log.info("My Runnable has finished for now!");
}
}
If log a message is not enough you can call a method of another object instead.
Exceptions under the wood
Another (most) probable cause is an uncaught exception thrown during the task execution. Within a thread pool, an unchecked exception like this will abruptaly stop the method execution and (surprisely) be swallowed into a java.util.concurrent.FutureTask object. In order to avoid things like this, I use the following idiom:
class MyRunnable implements Runnable {
public void run() {
while(/*some condition*/) {
try {
// do my things
} catch (Throwable throwable) {
handle(throwable);
}
}
log.info("My Runnable has finished for now!");
}
private void handle(Throwable throwable) {
// ...
}
}
or depending on the logic/performance requirements I also use:
public void run() {
try {
while(/*some condition*/) {
// do my things
}
} catch (Throwable throwable) {
handle(throwable);
}
System.out.println("My Runnable has finished for now!");
}
The code below exemplify the issues commented here in action:
package mypocs;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
public class ExceptionSwallowingInThreadPoolsPoC {
public static void main(String[] args) {
ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
final Object LOCK = new Object();
threadPoolExecutor.submit(() -> {
while (true) {
synchronized (LOCK) {
System.out.println("Thread 'A' never ends");
}
Thread.sleep(1000L);
}
});
threadPoolExecutor.submit(() -> {
int lifespan = 3;
while (lifespan > 0) {
synchronized (LOCK) {
System.out.println("Thread 'B' is living for " + lifespan + " seconds");
}
lifespan--;
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Thread 'B' finished");
});
threadPoolExecutor.submit(() -> {
int lifespan = 3;
while (lifespan > 0) {
synchronized (LOCK) {
System.out.println("Thread 'C' is living for " + lifespan + " seconds");
}
lifespan--;
if (lifespan < 1) {
throw new RuntimeException("lifespan reached zero");
}
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Thread 'C' finished");
});
while (true) {
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (LOCK) {
System.out.println("==== begin");
System.out.println("getActiveCount: " + threadPoolExecutor.getActiveCount());
System.out.println("getCompletedTaskCount: " + threadPoolExecutor.getCompletedTaskCount());
System.out.println("getPoolSize: " + threadPoolExecutor.getPoolSize());
System.out.println("==== end");
}
}
}
}
The code should output something like:
Thread 'A' never ends
Thread 'B' is living for 3 seconds
Thread 'C' is living for 3 seconds
Thread 'C' is living for 2 seconds
==== begin
getActiveCount: 3
getCompletedTaskCount: 0
getPoolSize: 3
==== end
Thread 'B' is living for 2 seconds
Thread 'A' never ends
==== begin
getActiveCount: 3
getCompletedTaskCount: 0
getPoolSize: 3
==== end
Thread 'C' is living for 1 seconds
Thread 'B' is living for 1 seconds
Thread 'A' never ends
Thread 'B' finished
==== begin
getActiveCount: 1
getCompletedTaskCount: 2
getPoolSize: 3
==== end
Thread 'A' never ends
Thread 'A' never ends
...
The class (ConditionObject) you are referring to is used to lock objects from being accessed concurrently by multiple threads. The Javadoc doesn't describe the thread state you mention, but here is my guess:
Your locked object is being blocked by one thread so long, that the other threads start to pile up on the lock. Once the thread holding the lock releases it, the next thread continues the aquire the lock. Until that new thread has done his work, new threads pile up behing the lock.
If my guess is right, then could:
reduce the time that each thread spends in the lock, or
distribute the threads on different locked things (if your problem permits that), or
you use an implementation that doesn't require locking.
Without knowing your problem domain, I hope that the information above is enough to point you into some direction that might be of help for you.
I'm making a very simple program in java, even because I'm a student. I made a program that count 1 at 1000, and when the number is multiple for 2 the thread is suspended for about 500ms. That's ok. But in the final, I need to show how many times the thread has been suspended. Like
System.out.println("The thread has been suspended for: " );
I have no idea. I appreciate any help.
#Override
public void run () {
for (int i = 0; i < 1000; i++) {
if (i % 2 == 0) {
try {
System.out.println(i);
Thread.sleep(500);
} catch (InterruptedException ex) {
Logger.getLogger(ThreadNumeros.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
System.out.println("thread has been suspended for: ");
}
DO NOT MIX (SUSPENDED) WITH (SLEEP): they work differently.
Thread.sleep() sends the current thread into the "Not
Runnable" state for some amount of time. The thread keeps the monitors
it has acquired -- i.e. if the thread is currently in a synchronized
block or method no other thread can enter this block or method. If
another thread calls t.interrupt() it will wake up the sleeping
thread.
t.suspend() is deprecated. Using it is possible to halt a
thread other than the current thread. A suspended thread keeps all its
monitors and since this state is not interruptable it is deadlock
prone.
stop(), suspend(), resume() are the methods used for thread
implementation. stop() - terminate the thread execution, Once a thread
is stopped, it cannot be restarted with the start() method, since
stop() will terminate the execution of a thread. Instead you can pause
the execution of a thread with the sleep() method. The thread will
sleep for a certain period of time and then begin executing when the
time limit is reached. But, this is not ideal if the thread needs to
be started when a certain event occurs. In this case, the suspend()
method allows a thread to temporarily cease executing. resume() method
allows the suspended thread to start again.
Synchronization-: If you declare any method as synchronized, it is known as a 'synchronized method'.
A synchronized method is used to lock an object for any shared resource.
When a thread invokes a synchronized method, it automatically acquires
the lock for that object and releases it when the thread completes its
task.
TRY LIKE THIS-:
#Override
public void run() {
int count = 0;
for (int i = 0; i < 1000; i++) {
if (i % 2 == 0) {
try {
System.out.println(i);
Thread.sleep(500);
count+=1
} catch (InterruptedException ex) {
Logger.getLogger(ThreadNumeros.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
System.out.println("thread has been suspended for: "+count);
}
I have just written a simple java example to get familiar with the concept of wait and notify methods.
The idea is that when calling notify(), the main thread will print the sum.
MyThread class
public class MyThread extends Thread {
public int times = 0;
#Override
public void run() {
synchronized (this) {
try {
for (int i = 0; i < 10; i++) {
times += 1;
Thread.sleep(500);
if (i == 5) {
this.notify();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Main Class
public class Main {
public static void main(String[] args) {
MyThread t = new MyThread();
synchronized (t) {
t.start();
try {
t.wait();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(t.times);
}
}
}
Expected Results
5 but I got 10 instead.
Well, what I though is that when notify() is called, the main thread will wakeup and execute the System.out.println(t.times) which should give 5. Then the run() will continue till it finishes the for loop which will update the value of times to 10.
Any help is highly appreciated.
Synchronized blocks imply mutual exclusion. At any given moment, only one thread is allowed to hold the lock and execute the code within a synchronized block. This rule spreads over all the blocks guarded by the same lock.
In your case, there're two such blocks that use the same lock, so it's either the main thread or the MyThread that is allowed to execute code in either of these blocks, the other thread must wait. So, you have the following scenario here:
The main thread acquires the lock.
The main thread starts the second thread.
The second thread hits the synchronized block but cannot enter it since the lock is being hold by the main thread.
The main thread calls wait(). This call releases the lock and puts the main thread into the WAITING state.
The second thread now can acquire the lock and enter the synchronized block.
The second thread counts to five and calls notify(). This call doesn't release the lock, it just notifies the main thread that it can progress as soon as it can reacquire the lock.
The main thread awakes but it cannot make progress because it cannot reacquire the lock (it's still being hold by the second thread). Remember, no two threads can be active within a synchronized block guarded by the same lock at once, and now, the second thread is still active, so the main one must continue waiting.
The second thread continues counting, sets times to 10 and eventually leaves the synchronized block, releasing the lock.
The main thread reacquires the lock and can now make progress to the println. But by this time, the times is already 10.
Using join() won't help you either because the result will be the same – the main thread can only make progress when the second one is finished.
If you want your main thread to continue execution as soon as the second thread hits 5, you need to acquire the lock and release it immediately after that event:
public class MyThread extends Thread {
public volatile int times = 0;
#Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
times += 1;
Thread.sleep(500);
if (i == 5) {
synchronized(this) {
this.notify();
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
Don't forget to make times volatile, otherwise JVM won't guarantee that you'll see its actual value in your main thread.
And you should also understand that this approach doesn't guarantee that your main thread prints 5. It might occur that by the time it reaches the println call, the second thread makes one or two or even more iterations and you'll see something greater than 5 (though it's highly unluckily due to the sleep() call on every iteration).
public class ThreadA {
public static void main(String[] args) {
ThreadB threadB = new ThreadB();
threadB.start();
synchronized (threadB) {
try {
threadB.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("the total is ====>"+threadB.total);
}
}
class ThreadB extends Thread
{
int total;
public void run(){
synchronized (this) {
for(int i =0; i<5;i++)
{
System.out.println("lets add===>"+i);
total+= i;
}
notify(); // line no.31
System.out.println("after notify but within lock");
}
System.out.println("after notify but outside lock");
}
}
output :
lets add===>0
lets add===>1
lets add===>2
lets add===>3
lets add===>4
after notify but within lock
the total is ====>10
after notify but outside lock
My question : shouldn't the control go back to the "Main" thread immediately after line no.31. Ideally shouldn't it print -
"the total is ====>10" immediately after "lets add===>4"?
Why it is that it executes all the statements within the synchronized block irrespective of the notify() statement in line no.31?
the order of last couple of lines will not be same always. it depends on the how the threads are being scheduled and there is no guarantee, based on the code you have. the moment you have executed notify the wait is over, so any thread can run in any order. however after notify but within lock is within lock so even if main thread is executed its locked and can't do anything
My question : shouldn't the control go back to the "Main" thread immediately after line no.31.
You're asking for the impossible. The thread that called notify is still in a synchronized block. Once the other thread finishes waiting, it's back in the synchronized block. So what you are asking for would require two threads to be in synchronized blocks on the same object at once, which is precisely what such blocks prohibit.
synchronized (threadB) {
try {
threadB.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("the total is ====>"+threadB.total);
So this code does this:
Enter synchronized block.
Call wait.
Exit synchronized block.
Print the total.
Notice:
We can't exit the synchronized block unless we're in the synchronized block; and
We can't exit the synchronized block until we return from wait; thus
We can't go from wait to printing the total without being in the synchronized block, thus we cannot do so while another thread remains in the synchronized block or else there would be two threads in the synchronized block at once.
Now look at this code:
notify(); // line no.31
System.out.println("after notify but within lock");
} // exit synchronized block
So any thread that notifies another thread does not leave its synchronized block until after it prints. Thus the notified thread cannot exit its synchronized block until after the print either.
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.