I have a semaphore which restricts users to download n number of files at a time. Each file is downloaded in a separate thread.
EDIT: Modified the example so that the release happens correctly
import java.util.concurrent.Semaphore;
public void downloadFile() {
Thread downloadThread = new Thread() {
boolean bSemaphoreAcquired = false;
public void run() {
try {
semaphore.acquire();
bSemaphoreAcquired = true;
// do the download
} catch (InterruptedException e) {
} finally {
if (bSemaphoreAcquired) semaphore.release();
}
}
};
// add download thread to the list of download threads
downloadThread.start();
}
Now, any new downloads will wait for the previous downloads to finish once all the permits of the semaphore have been acquired.
When the user chooses to cancel a download that is waiting at the acquire call I call the interrupt() method to terminate that download thread.
The problem I am facing is that once this semaphore has been interrupted it would not throw the InterruptedException exception the second time!! Any new thread that is created will just wait on the acquire method for ever!
Sequence of events (Semaphore that permits 2 threads)
- thread 1 downloading
- thread 2 downloading
- thread 3 waiting on acquire()
- thread 3 is cancelled (interrupt() is called). InterruptedException is thrown and the thread exits
- thread 4 is created and is now waiting on acquire()
- thread 4 is cancelled (interrupt() is called). InterruptedException IS NOT THROWN ANYMORE!!!
This is the stack trace of thread 4
Semaphore$FairSync(AbstractQueuedSynchronizer).fullGetFirstQueuedThread() line: 1276
Semaphore$FairSync(AbstractQueuedSynchronizer).getFirstQueuedThread() line: 1232
Semaphore$FairSync.tryAcquireShared(int) line: 201
Semaphore$FairSync(AbstractQueuedSynchronizer).acquireSharedInterruptibly(int) line: 1142
Semaphore.acquire() line: 267
FileDownloadManager$1.run() line: 150
Why does thread 4 not receive the exception?
I would suggest using standard thread pool instead of semaphores.
The problem with your solution is that you create a new thread regardless of whether you reached max limit or not. So if you have 1000 simultaneous requests you will create 1000 threads which is really wasteful.
Instead try something like this:
ExecutorService executorService = Executors.newFixedThreadPool(5);
executorService.submit(new Runnable() {
public void run() {
// do download
}
});
Are you releasing the semaphore within the catch?
Why not put the try-catch within the aquire-release. Not sure what java does, but wouldnt that be more logical. That way any problem within the try...catch always ends with the semaphore being released.
Related
This question already has an answer here:
Why await of Condition releases the lock but signal does not?
(1 answer)
Closed 8 months ago.
Java doc for Condition.await():
The lock associated with this Condition is atomically released and the
current thread becomes disabled for thread scheduling purposes and
lies dormant until one of four things happens:
Some other thread invokes the signal method for this Condition
...
I wrote a test program to see, after Thread-1 calls Condition.await() and gets blocked, Thread-2 calls Condition.signal().
I expect Thread-1 should return immediately from await() and continue.
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.*;
public class TestThreadCondition {
public static void main(String[] args) throws InterruptedException {
Lock rLock = new ReentrantLock();
Condition cond = rLock.newCondition();
AtomicBoolean aBool = new AtomicBoolean(true);
Thread t1 = new Thread(new Runnable() {
#Override public void run() {
try {
rLock.lock();
System.out.println("(Step 1) Thread 1 locks and sleeps 1s");
Thread.sleep(1000);
while (aBool.get()) {
System.out.println("(Step 3) Thread 1 enters while loop");
cond.await();
System.out.println("(Step 5) Thread 1 got signal");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
rLock.unlock();
}
}
});
t1.start();
Thread t2 = new Thread(new Runnable() {
#Override public void run() {
try {
Thread.sleep(300);
System.out.println("(Step 2) Thread 2 also requires lock, blocked");
rLock.lock();
System.out.println("(Step 4) Thread 2 gets lock after thread 1 cond wait, sends signal");
cond.signal(); // I hope this would signal "t1" and t1 will enter (Step 5) immediately.
System.out.println("(Step 6) Thread 2 sleeps 3s and set aBool");
Thread.sleep(3000);
aBool.compareAndSet(true, false);
} catch (Exception e) {
e.printStackTrace();
} finally {
rLock.unlock();
System.out.println("(Step 7) unlock");
}
}
});
t2.start();
t1.join();
t2.join();
}
}
I expected that this program will run and print
Step1->Step2->Step3->Step4->Step5->Step6->Step7.
But the actual result was:
(Step 1) Thread 1 locks and sleeps 1s
(Step 2) Thread 2 also requires lock, blocked
(Step 3) Thread 1 enters while loop
(Step 4) Thread 2 gets lock after thread 1 cond wait, sends signal
(Step 6) Thread 2 sleeps 3s and set aBool
(Step 7) unlock
(Step 5) Thread 1 got signal
The Step 5 was executed after Step6 and Step7. It looks like that in Thread-1, cond.await() was not awaken when Thread-2 called cond.signal, and it blocks until Thread-2 called rLock.unlock().
This seems conflicts with the Javadoc's explanation, as I stated at the beginning. How to understand the behavior of my code?
At the time your code prints
(Step 5) Thread 1 got signal
Thread1 has already exited the await method. It cannot have gotten that far without already having acquired the lock. So naturally that can't happen if another thread still has the lock.
So your code isn't a good test, we don't know from it whether the signal was delayed until the lock was released, or if the signal occurred earlier than that and thread1 was woken up but was blocking on getting the lock.
In the comparable situation with intrinsic locks it is spelled out in the apidoc that notify is delayed until the notifying thread releases its lock. The waiting thread can't act until then anyway. If that same situation occurs here that would not be surprising.
There isn't a contradiction in the javadoc in any case, waking up and acquiring the lock are two different things.
public class ThreadTest {
public static void main(String[] args) throws InterruptedException {
ExampleTest obj = new ExampleTest();
Thread t1 = new Thread(new Runn(obj));
Thread t2 = new Thread(new Runn(obj));
Thread t3 = new Thread(new Runn(obj));
t1.start();
t2.start();
t3.start();
//Thread.sleep(1);
obj.exit();
}
}
class ExampleTest {
public synchronized void enter() {
try {
System.out.println("printed " +Thread.currentThread().getName() +" inside wait");
this.wait();
System.out.println("printed " +Thread.currentThread().getName() +" exit wait");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("printed " +Thread.currentThread().getName() +" at time: "+System.currentTimeMillis());
}
public synchronized void exit() {
this.notifyAll();
}
}
class Runn implements Runnable {
ExampleTest obj;
public Runn(ExampleTest obj) {
this.obj = obj;
}
#Override
public void run() {
obj.enter();
}
}
what is the role of notifyAll(). Will notifyAll() allows all the waiting thread to acquire lock sequentially in random order or only one thread can acquire the lock?
Without the sleep statement the statement obj.exit(); will be very likely be executed before all of your threads reaching their wait status. ie. the notifyAll call will be over before at least one of your thread is in wait status. So at least one of your threads will be stuck in wait status waiting for some other thread to notify it and wake up. But that will never happen as obj.exit() is already finished.
With your sleep statement in place , all of your threads will get a chance to reach their wait status and your notifyAll call after the sleep will wake them all, The order of waking up will not be deterministic and will be handled by the thread scheduler.
Your code suffers from the "lost notification" syndrome, which is alleviated (but not deterministically avoided) by the sleep call.
You haven't provided any mechanism which would ensure that, at the time of calling exit, all the threads have already reached their wait call. Therefore some threads will miss the notification and enter an eternal wait state.
The notifyAll call does wake up all waiting threads, but it doesn't wake up threads which enter the wait state in the future.
With the following code:
t1.start();
t2.start();
t3.start();
You are starting the threads. Starting threads might take some time as it involves memory allocation and other operations. When your threads run they enter a wait state. Started threads do not, however, execute immediately. They start executing as soon as the scheduler decides it is time for them to execute. When you call start the main thread is currently running on the CPU. Without the sleep most likely the main thread will keep the CPU and call:
obj.exit();
Before the threads actually started, that is, before the threads actually entered the wait state. The notifyAll will execute in vain, as threads are not started yet and therefore are not waiting. The notification will be lost.
With the sleep call you are suspending the main thread for quite some time (for the CPU perspective). This means that the other threads will most likely get the CPU and enter the wait state. So when you then call notifyAll this time the notification will not get lost. Notice that there is no guarantee that this will happens: it might still happen that when you call exit() some (or all) other threads have not yet executed their wait.
I write the below code to test when will the thread is awake when it is waiting for a Condition object.
But I find I have to unlock after I call signal(). Lock is not release by this method, while await() will release this lock .
This is from Condition#await
The lock associated with this Condition is atomically released and the current thread becomes disabled for thread scheduling purposes and lies dormant until one of four things happens:
And this is from Conditon#signal
Wakes up one waiting thread.
If any threads are waiting on this condition then one is selected for waking up. That thread must then re-acquire the lock before
returning from await.
But in my code, this is not true, until we unlock the lock. Why it is design like this? Since in my opinion, when we decide to to signal the others, we should not hold the lock any more,am I wrong?
Since we can do many things between calling signal and unlock ,say I sleep 10 seconds, what exactly the time java signal the other thread? Is there a another background thread who is working between we signal and unlock?
public class WorkerThread extends Thread{
#Override
public void run() {
Monitor.lock.lock();
while (!Monitor.isConditionTrue){
try {
Monitor.condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("THREAD ID "+this.getId()+"-------working --------");
System.out.println("------singnall--------");
Monitor.isConditionTrue=true;
Monitor.condition.signal();
try {
Thread.sleep(3000);//here, the thread is sleeping while another thread is not awaken since the lock is not releases
System.out.println("------unlock--------");
Monitor.lock.unlock();//now the other thread is awaken, if I do not explicitly unlock , no thread will be awaken.
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Monitor {
static ReentrantLock lock = new ReentrantLock();
static Condition condition = lock.newCondition();
static volatile boolean isConditionTrue = true;
public static void main(String args[]) {
Thread t1 = new WorkerThread();
Thread t2 = new WorkerThread();
t1.start();
t2.start();
Thread.sleep(2000);
lock.lock();
isConditionTrue=true;
condition.signalAll();
lock.unlock();
}
}
OUTPUT:
THREAD ID 9-------working --------
------singnall--------
------unlock--------
THREAD ID 10-------working --------
------singnall--------
------unlock--------
You have missed this sentence in Contition#await:
In all cases, before this method can return the current thread must re-acquire the lock associated with this condition. When the thread returns it is guaranteed to hold this lock.
In other words, you must explicitly release the lock after await, just as with signal.
Why this mechanism is sound: if you first released the lock, then signaled, you'd be open to race conditions where other threads made changes between releasing the lock and the signal reaching a parked thread. The way the mechanism works, first a definite thread is chosen to be awoken by the signal, then it waits for the lock, then the signaling thread releases it, then the awoken thread goes on.
You might argue that signal could do all of this internally, but then:
the API would become confusing: there would be more than one method releasing the lock;
the APi would become more restrictive and preclude any use cases where the thread wants to do something more before releasing the lock, such as atomically issuing more signals.
If my thread receives an InterruptedException in a sleep(), how can I tell whether it was caused by a call on its .interrupt() or .notify() method?
The long story:
I have a View() class running in a thread. It should run worker(s) and update the view from time to time. It should also measure the time the worker took. The View() should be interruptable by the application (upon shutdown). The workers should wake up (notify) the thread during sleep when they have finished to measure the time they took. (Without notification, time measured would be rounded up to the next full sleep cycle which isn’t desired.) So an InterruptedException can be triggered by a call on the thread’s .interrupt() or .notify() method. How do I distinguish this inside the catch block?
public class View() implements Runnable {
Long started = null;
Long finished = null;
#Overload
public void run(){
Set<Thread> workers = new HashSet<Thread>();
for(int i = 1; i <= 5; i++){
Thread worker = new Thread(new Worker());
worker.start();
workers.add(worker);
}
started = System.getCurrentTimeMillis();
do{
try{
TimeUnit.SECONDS.sleep(3);
updateView();
}catch(InterruptedException e){
if(--> thread_was_notified <--){
finished = System.getCurrentTimeMillis();
updateView();
}
if(--> thread_was_notified <--){
for(Thread worker : workers)
worker.interrupt();
}
return;
}
}while(true);
}
protected void updateView(){
// …
}
}
I first guessed that InterruptedException would have Subclasses, but there are none directly known subclasses listet in the javadoc. Thread provides .isInterrupted(), but as said here: “By convention, any method that exits by throwing an InterruptedException clears interrupt status when it does so.” So I can’t tell from .isInterrupted() either. What’s the clean way to do it?
I have a vegue idea that my code should use Object.wait(), but what’s the waiting object?
The ugly solution:
Instead of having your Workers interrupting the View thread, put a method like this:
public void workedFinished() {
interruptedByWorker = true; // View attribute.
viewThread.interrupt(); // Interrupt the view
}
Then, when you're on your catch, check for the interruptedByWorker boolean. If it is true, it was interrupted by a worker. Otherwise (make sure this is happens), it was interrupted by the shutdown.
The other solution
Instead of interrupting the thread in two different places (which I think it could be confusing an error-prone), you could do the following:
1) Schedule a Runnable to run every 3 seconds using a ScheduledExecutorService to update the view.
2) Have a CountdownLatch that is notified for each Worker that finishes. Please, notice that in your code, the first thread wakes up the View, meaning that the measured time will be only for that thread, it will not wait until the other threads finish.
InterruptedException is only thrown when some thread interrupts you and not thrown when comming out of wait().
So when you are in sleep() or wait() and some other thread decides to interrupt you then Exception will be thrown.
When a thread is in wait() state and notify() is called for it then it will again fetch the lock and resume its working without throwing any exception.
I'm now trying to add an update checking module into my program. The method is processing a website for update informations. But in some situations the website is not accessable, and the program stops checking in 0.5 seconds. To make this possible, I wrote these code:
int[] lock = new int[0];
boolean fileListGot = false;
Thread downloadFile = new Thread() {
public void run() {
synchronized (lock) {
fileList = HttpFetcher.fetch("http://*****/****");
fileListGot = true;
lock.notify();
}
}
};
synchronized (lock) {
downloadFile.start();
lock.wait(500);
}
return fileListGot;
But the program doesn't stop after 0.5 seconds. What the wrong with the program? And how to use Object.wait(long)?
Read the Object.notify javadocs - the important part being "The awakened thread will not be able to proceed until the current thread relinquishes the lock on this object. "
The main thread acquires the monitor of lock. It starts the worker thread. The worker thread attempts to gain lock's monitor, but cannot. The main thread then calls lock.wait(500) and so loses the monitor. The worker thread then gains the monitor and proceeds. If the download is still going on after 500ms, wait returns and the main thread attempts to gain the monitor, but it is still owned the worker thread.
You don't need to hold the monitor when downloading the file, only when mutating the shared variables - try this instead
public void run() {
T temp = HttpFetcher.fetch("http://*****/****");
synchronized (lock) {
fileList = temp;
fileListGot = true;
lock.notify();
}
}
where T is the appropriate type for fileList
You enter synchronized block then start a thread. The thread's run tries to enter synchronized block and waits forever because you have already taken the same lock from another thread.
Move downloadFile.start() away from synchronized block.