Differences between synchronized keyword and ReentrantLock [duplicate] - java

This question already has answers here:
What's the difference between Synchronized and Lock in my example?
(2 answers)
What's the difference in using ReentrentLock and Synchronized(object)? [duplicate]
(1 answer)
Closed 5 years ago.
I made a thread pool based on the example on this page.
In the worker thread we have the infinite loop that never lets the thread die and the wait() method call that pauses the thread when there is no work to do:
while (true) {
synchronized(queue) {
loop:while (queue.isEmpty()) { // labled the loop so we can return here
try
{
queue.wait();
if(queue.isEmpty()) // check the condition predicate again
continue loop;
}
catch (InterruptedException ignored)
{
}
}
r = (Runnable) queue.removeFirst();
}
// If we don't catch RuntimeException,
// the pool could leak threads
try {
r.run();
}
catch (RuntimeException e) {
// You might want to log something here
}
The fact is that r = (Runnable) queue.removeFirst(); can throw a NoSuchElementException which is a RuntimeException if the queue is empty. And when such an exception is thrown on that line, the current thread holding the mutex dies and the pool leaks the thread. The mutex seems to be released when the thread dies.
However, if you instead of using the default synchronized keyword to synchronize the queue, use the ReentrantLock to lock and Condition for signaling and awaiting, the current thread that holds the mutex does not seem to release the lock when it interrupts unexpectedly.
So, in my case, when I checked with JVisualVM under the Threads tab I could see that the AWT-EventQueue-0 thread was wating for Thread-1 to release the mutex. But the Thread-1 died upon its way to run the task and was unexpectedly terminated (RuntumeException) and the mutex did not seem to be released.
My questions:
1) Does not ReentrantLocks being released if the thread that holds it terminates unexpectedly?
2) Is there any difference between while (queue.isEmpty()) { and if (queue.isEmpty()) { in the code snippet above? I cannot see any difference since the thread will wait in both cases. But I think the behaviour it different when using if (like if more than one thread can affect the queue).
EDIT
Java Concurrency in Practice states:
For all these reasons, when you wake up from wait you must
test the condition predicate again, and go back to waiting
(or fail) if it is not yet true. Since you can wake
up repeatedly without your condition predicate being true, you
must therefore always call wait from within a loop, testing
thecondition predicate in each iteration.
Look at my edit in the code above, now the code should be correctly as stated in Java Concurrency in Practice.

1) Does not ReentrantLocks being released if the thread that holds it terminates expectedly?
Lock release only when you call Lock#unlock() explicitly. That why recommend to invoke Lock#unlock() in finally block to prevent deadlocks in your application.
2) Is there any difference between while (queue.isEmpty()) { and if
(queue.isEmpty()) { in the code snippet above? I cannot see any
difference since the thread will wait in both cases. But I think the
behaviour it different when using if (like if more than one thread can
affect the queue).
There, no big differences in particular situation. But using while you guarantee assert in your application, you will not invoke removeFirst() when Queue is empty.
Also, PROS for using while instead of if is spurious wakeups.
notes:
If you are implementing this schema not only for education, consider using BlockingQueue. java.util.concurrent library resolved many multithread problems and in most cases you can build application based on the high level abstractions of java.util.concurrent instead of using low-level techniques such as wait()/notify().

Your code seems too complicated - I would simply write:
while (true) {
synchronized(queue) {
while (queue.isEmpty()) {
try {
queue.wait();
} catch (InterruptedException ignored) {
//don't ignore me please
//you probably should exit the loop and return here...
}
}
r = queue.removeFirst(); //Why use a cast? Use generics instead.
}
}
The only situation where queue.removeFirst() could throw a NoSuchElementException is if it is modified concurrently, which is not possible if all accesses to the queue are made in synchronized blocks.
So find the place where you access the queue without holding the lock on the monitor and you will solve your problem.
The reason why you must call wait within a loop is that wait might wake spuriously (i.e. because wait wakes up does not mean your condition has become true so you need to test it again).
As a side note, if you used a BlockingQueue you would not have to worry about those low level details and you could simply write:
while(true) {
Runnable r = queue.take(); //blocks until queue is not empty
}

Stuff in java.util.concurrent give you more flexibility and things like timed waits and try-lock/acquire methods. Also, synchronized gives you code block, unlike lock.lock()/unlock() pairs. It also tends to be more efficient when there is no contention.
Anyway, when using concurrency, one should definitely look into java.util.concurrent since many problems are solved there already.

Related

Best practices for handling InterruptedException [duplicate]

This question already has answers here:
Handling InterruptedException in Java
(7 answers)
Closed 4 years ago.
In business scenario, InterruptException occurs multiple times, some before the business code is executed, and some after the business code. How to deal with InterruptException makes me confused.
    
1. preBusiness code semaphore.acquire()
try {
semaphore.acquire();
} catch (InterruptedException e) {
// do something
}
resObj = caller.stepTry();
semaphore.release();
postBusiness code latch.await(), service.take().get()
CompletionService<CallableResultBO> service = new ExecutorCompletionService<>(executor);
CountDownLatch latch = new CountDownLatch(size);
for (R callable : listCall){
callable.setCountParam(JdkThreadCountBO.buildByLatch(latch));
service.submit(callable);
}
try {
latch.await();
} catch (InterruptedException e) {
// do something
}
CallableResultBO[] resArr = new CallableResultBO[size];
for ( int i = 0; i < size; i++ ){
try {
resArr[i] = service.take().get();
} catch (InterruptedException e) {
// do something
} catch (ExecutionException e) {
// do something
}
}
There are also some doubts found in practice, and I am still thinking about how to draw conclusions.
     A thread can't be interrupted casually. Even if we set the interrupt state for the thread, it can still get the CPU time slice. Usually only threads blocked by the sleep() method can immediately receive an InterruptedException, so in the case of a sleep interrupt task, you can use try-catch to jump out of the task. In other cases, it is necessary to determine whether the task needs to be jumped out (Thread.interrupted() method) by judging the thread state.
     In addition, the code modified by the synchronized method will not be interrupted immediately after receiving the interrupt signal. The synchronization code of the ReentrantLock lock control can be interrupted by InterruptException.
Generally, you are advised to do the following:
void methodThatWaits()
{
try
{
Thread.sleep( 1000 );
}
catch( InterruptedException e )
{
//e.printStackTrace();
Thread.currentThread().interrupt();
}
}
So, no, Thread.currentThread().interrupt(); is not redundant.
This is known as the Java Thread.currentThread().interrupt idiom, and it is explained in detail in Java Concurrency in Practice, Chapter 7.1.3. It is also mentioned in Effective Java, you can read an excerpt here: Google Books - Effective Java - search for java idiom thread interrupt interruptedexception josh bloch
All the java.util.concurrent classes use interruption uniformly, to indicate that the receiving thread should wind up what its doing and terminate. It seems to me it only makes sense to follow the same guidelines when writing code that uses these classes.
When something throws InterruptedException the interrupt flag for that thread is cleared. Calling Thread.currentThread().interrupt restores the flag to its previous value.
For toy examples in tutorials restoring the flag seems stupid, because it’s in a catch block at the end of a run method and the thread is terminating immediately anyway. The point is that there may be many layers of things going on within a thread, you may have a Runnable task submitted to a threadpool where that task is talking to a blocking queue, etc., where every participant needs to know if an interrupt occurs so they can all arrive at a stopping point and finish gracefully. If any one of these eats the InterruptedException without restoring the flag, somebody may miss hearing about the interrupt, the thread will keep on working, and your application may not quit cleanly.
Not finishing cleanly can mean:
There may be half-done work hanging out to dry as a result.
Threads are GC roots, so you may get a memory leak.
Any non-daemon thread that stays alive keeps the JVM from exiting.
For what to do with InterruptedException: Synchronizers in java.util.concurrent tend to let it be thrown. Whether you do that or not depends on what you need to do to finish things up. Thread cancellation is voluntary so that you can make sure your task gets cleaned up reliably.

Java - Priority in semaphore

I have multiple threads accessing an external resource – a broswer. But only one thread can access it at a time. So, I am using a semaphore to synchronise them. However, one thread, which takes input from the GUI and then access the browser for the results, should have priority over other threads and I am not sure how to use a semaphore to achieve it.
I was thinking that every thread after acquiring the semaphore checks if there is the priority thread waiting in the queue and if yes, then it releases it and waits again. Only the priority thread doesn't release it once it is acquired.
Is this a good solution or is there anything else in Java API I could use?
There're no synchronization primitives in Java that would allow you to prioritise one thread over others in the manner you want.
But you could use another approach to solving your problem. Instead of synchronizing threads, make them produce small tasks (for instance, Runnable objects) and put those tasks into a PriorityBlockingQueue with tasks from the GUI thread having the highest priority. A single working thread will poll tasks from this queue and execute them. That would guarantee both mutual exclusion and prioritization.
There're special constructors in ThreadPoolExecutor that accept blocking queues. So, all you need is such an executor with a single thread provided with your PriorityBlockingQueue<Runnable>. Then submit your tasks to this executor and it will take care of the rest.
Should you decide to choose this approach, this post might be of interest to you: How to implement PriorityBlockingQueue with ThreadPoolExecutor and custom tasks
Here's a simple, no frills answer. This is similar to how a read/write lock works, except that every locker has exclusive access (normally all readers proceed in parallel). Note that it does not use Semaphore because that is almost always the wrong construct to use.
public class PrioLock {
private boolean _locked;
private boolean _priorityWaiting;
public synchronized void lock() throws InterruptedException {
while(_locked || _priorityWaiting) {
wait();
}
_locked = true;
}
public synchronized void lockPriority() throws InterruptedException {
_priorityWaiting = true;
try {
while(_locked) {
wait();
}
_locked = true;
} finally {
_priorityWaiting = false;
}
}
public synchronized void unlock() {
_locked = false;
notifyAll();
}
}
You would use it like one of the Lock types in java.util.concurrent:
Normal threads:
_prioLock.lock();
try {
// ... use resource here ...
} finally {
_prioLock.unlock();
}
"Priority" thread:
_prioLock.lockPriority();
try {
// ... use resource here ...
} finally {
_prioLock.unlock();
}
UPDATE:
Response to comment regarding "preemptive" thread interactions:
In the general sense, you cannot do that. you could build custom functionality which added "pause points" to the locked section which would allow a low priority thread to yield to a high priority thread, but that would be fraught with peril.
The only thing you could realistically do is interrupt the working thread causing it to exit the locked code block (assuming that your working code responded to interruption). This would allow a high priority thread to proceed quicker at the expense of the low priority thread losing in progress work (and you might have to implement rollback logic as well).
in order to implement this you would need to:
record the "current thread" when locking succeeds.
in lockPriority(), interrupt the "current thread" if found
implement the logic between the lock()/unlock() (low priority) calls so that:
it responds to interruption in a reasonable time-frame
it implements any necessary "rollback" code when interrupted
potentially implement "retry" logic outside the lock()/unlock() (low priority) calls in order to re-do any work lost when interrupted
You are mixing up concepts here.
Semaphores are just one of the many options to "synchronize" the interactions of threads. They have nothing to do with thread priorities and thread scheduling.
Thread priorities, on the other hand are a topic on its own. You have means in Java to affect them; but the results of such actions heavily depend on the underlying platform/OS; and the JVM implementation itself. In theory, using those priorities is easy, but as said; reality is more complicated.
In other words: you can only use your semaphore to ensure that only one thread is using your queue at one point in time. It doesn't help at all with ensuring that your GUI-reading thread wins over other threads when CPU cycles become a problem. But if your lucky, the answer to your problem will be simple calls to setPriority(); using different priorities.

Only one thread have access to a certain part of code?

I have a project which requires logging in my router from time to time and make some changes. In eclipse I have a separate project which deals with all the things I need changed and I have that in the build path of my main project which is a multi threaded project. My problem is that sometimes two threads try to access the router which messes things up. Is there anything I can do that only one thread can access a certan part of my code.
This is the related code for the main multithreaded application
if (totalLogins > 10)
{
IpManager.rebootRouter();
Thread.sleep(4000);
totalLogins = 0;
composedMessagesWithThisIP = 0;
}
And in the other project this is what I have
public synchronized static void rebootRouter()
{
try
{
//code related to restart modem
}
catch (Exception e)
{
}
}
So what I have done is made the method synchronized but I believe from time to time more than one thread access the "rebootRouter" method. Which causes problems in my main application.
What is the best way and most effective way to make IpManager.rebootRouter() be executed by one thread only?
Regards!
synchronized guarantees that only one thread can enter the block at a time, but AFAIR the same thread can enter the block multiple times (so threads don't deadlock against themselves), and if a thread is blocked because another thread is in there then it may run immediately after the first thread leaves the synchronized block.
First I'd throw logging at the entry and exit points of the routine.
I'd check to see that you don't have any recursion going on, and make sure that the calls really are running at the same time. Also, remember if there's any asynchronous work or callbacks the synchronized block may be exited.
Use Semaphore from java.util.concurrent package, to restrict the Number of thread accessing the object.
Example:
Here in this code snippet, only 1 thread can access the object at a time.
Semaphore s = new Semaphore(1);
s.acquire();
synchronized(this){
// Your modem work
}
s.release();
So what I have done is made the method synchronized but I believe from time to time more than one thread access the "rebootRouter" method.
As you have marked this method as synchronized it guarantees that more than one thread can not execute this method simultaneously . It may be code in side // Your modem work has some unsynchronized stuff that may cause problem.
My problem is that sometimes two threads try to access the router which messes things up. Is there anything I can do that only one thread can access a certan part of my code.
Define "messes things up". Since rebootRouter is synchronized, only one thread can run that method at any given time. But if a thread, call it thread A, tries to invoke it while another thread (thread B) runs it, thread A will block until B returns from rebootRouter, and A will then directly call rebootRouter itself. If this is the behavior you want, your problems are elsewhere (synchronized is not broken, or someone would've noticed).
If you want thread A in the example above to not invoke rebootRouter if it is called by another thread when in the example above, you can use Lock.tryLock:
private static final Lock lock = new ReentrantLock();
public static void rebootRouter() {
if (!lock.tryLock()) return;
try {
//code related to restart modem
} catch (Exception e) {
// Note: Empty catch blocks considered bad style
} finally {
lock.unlock();
}
}
If your needs are more specific, you probably need to rephrase your question.

Threading - why do we do use while(true) while waiting

In most of the threading examples in Java, there is common use of a while(true) block like this:
while(true) {
try {
wait()
} catch (Exception ex) {
/*do something*/
}
}
What is the purpose of using while (true) ? Under what kind of scenarios are they particularly useful?
Client/Server communications?
Thanks,
- Ivar
This kind of construct is used when we create Thread pools and re-usable threads. Basically the while(true) construct prevents the Threads of the pool to ever exit.
An example would be a Producer-Consumer situation where Threads wait() till until the queue is empty and as soon as the queue has data, they are notify()ied and one of the thread consumes the data from the queue and does the processing and then goes back to wait() for additional data to arrive again.
while(true) is useful if you want to do something all the time while your code is running and you don't know how often you have to do it.
Client/Server Communication is one scenario. Other scenarios are animations of games or keeping some values always up to date.
A Thread is seperated from the other code, so your application would not hang by using while(true).
It is usefull to add an exit-flag to your while(true)-loop, so you can stop it if you want to.
Boolean isExit = false; //set this value to true when needed.
while(true) {
try {
if(isExist){
break;
}
wait()
} catch (Exception ex) {
/*do something*/
}
}
This is how you implement a condition variable in Java:
synchronized (this) {
while (true) {
try {
wait();
if (someCondition) {
break;
}
} catch (InterruptedException ex) {
// handle the 'interrupt' case ...
}
}
// Do something that depended on the condition being true.
}
The wait call waits until some other thread does a notify on this, presumably to say that the condition is now true. However, it is possible that the condition has become false before the current thread woke up or that multiple threads were woken up. (Obviously, this depends on the application logic of whatever is calling notify or notifyAll.) So we (re-)check the condition and retry if it isn't true. That is the point of the while (true).
The wait() call must be performed inside a monitor lock on this, and the assumption is that this lock is protecting the state that someCondition is checking.
The other tricky thing is dealing with the InterruptedException that may be thrown by wait(). Some people think it is OK to just squash it. In fact, the correct thing to do is to either to propagate it or to call Thread.interrupt() to set the interrupted flag again, and stop whatever the thread is currently doing. If you don't do this, the thread is effectively going to ignore interrupts ... which is a bad thing.
FWIW - catching Exception rather than InteruptedException is bad practice, and possibly a bug.
The while true causes a infinite loop to stop the thread terminating, for example you don't want your server that is waiting for clients to connect to only check once then to stop checking, you want the server to keep checking over and over. Using a while loop allows you to break; out the loop if something goes wrong.
This is an infinite loop, thus the thread would wait infinitely until an exception (most likely an InterruptedException) occurs.
That example doesn't make much sense by itself, normally you'd do something after the wait() and then wait for the next notify from another thread. You'd then use while(true) to indefinitely wait for the notification, do some stuff, then wait again until the application throws an exception or some condition to break the loop is met.

Java strange thread termination

I have a system with multiple threads running - my main-thread just checks if there are jobs to be done and if there are some, it calls the sub-threads (notifyAll()) who will execute it. After that, the sub-threads just wait() until there are some new tasks.
Actually, the thread-system is running reliable, but after a longer runtime (3-5h), some sub-threads just die without a warning or an error. They just exit one after another - but again only with a time-range of 2-x hours. I have used jconsole to check this phenomenon, which threads are running and how they just simply disappear.
Furthermore, the main-thread is executing every second, but the sub-threads are mainly wait()ing and are not often used at all (since there are not so many tasks in the test environment).
The only reason I can think of is, that the JVM turns off the sub-threads since they are not often used enough?
I would be very thankfull for your help!
P.S. All threads are not defined as daemons and the main-thread just works fine!
edit
Thanks for your answers, but I actually use this loop.
public void addTask (Task in_task) throws InterruptedException {
synchronized (tasks) {
while (tasks.size() == MAXIMUM_NUMBER_OF_TASKS) {
tasks.wait();
}
tasks.offer(in_task);
tasks.notifyAll();
}
}
I use this loop, so that only some speciall amount of tasks will be executed.
The documentation for Object.wait() says:
As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop:
synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
}
Maybe you didn't follow this advice and got a spurious wakeup or interrupt?
Instead of writing your own multi-threaded task execution solution you could use java.util.concurrent.ThreadPoolExecutor. This would probably be a good idea no matter whether you are able to fix this bug or not.
I recommend using one of the Executors for managing your tasks. There are less chances that you will lose a possible error or exception in one of you sub-threads, so it should help you debug you program. Any exception that happens in a sub-thread will be stored inside the Future object and rethrown as an ExecutionException when you call Future#get().
List<Future<Void>> taskResults = new ArrayList<Future<Void>>();
ExecutorService es = Executors.newFixedThreadPool(NUMBER_OF_THREADS);
while(!finished){
//say you wait (blocking) for a new task here
Callable<Void> task = getNextTask();
//put the task into the pool
Future<Void> result = es.submit(task);
taskResults.add(result);
}
//3 hours later, set `finished` to true
//at the end check that no exceptions were thrown
for(Future<Void> result : taskResults){
try{
result.get();
}catch(ExecutionException e){
//there was an error
e.getCause().printStackTrace();
}catch(InterruptedException e){
//irrelevant
}
}
In general, stuff in the java.util.concurrent helps you write much more robust multi-threaded applications, without having to resort to Object#wait() and other concurrency primitives (unless you are learning, of course).
Try setting an uncaught exception handler on each thread.
There is a setUncaughtExceptionHandler() function on the Thread. Implement the UncaughtExceptionHandler interface and print the exception.
General idea, but don't do it with anonymous classes/methods:
thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler()
{
public void uncaughtException(Thread t, Throwable e)
{
e.printStackTrace();
}
});

Categories

Resources