If the thread holding a ReentrantReadWriteLock.writeLock() stops executing due to an uncaught exception, is the lock released, or is it held and all the other threads are now deadlocked?
I'll assume that by "fail", you mean an uncaught exception propagates off the top of the Thread's run method, causing it to stop executing.
If the thread used finally blocks properly, then it will have unlocked the writeLock on its way back up the stack.
If the thread didn't call unlock(), however, it still holds that monitor even though it's not running any more - so yes, other threads will be deadlocked.
This is why it's critical important to acquire and release resources correctly. And also a reason to stick with synchronized blocks unless/until you can establish that you need the functionality of specific locks - because they cannot fail to be released. (In your case I'm sure you do need the separate read/write locks, I'm making a more general point here.)
You must use a try-finally block when using "Explicit Lock", to release any lock that you acquired.
This is a key difference between using synchronized.
Related
Let's say you have two threads, thread1 and thread2. If you call thread1.start() and thread2.start() at the same time and they both print out numbers between 1 and 5, they will both run at the same time and they will randomly print out the numbers in any order, if I am not mistaken. To prevent this, you use the .join() method to make sure that a certain thread gets executed first. If this is what the .join() method does, what is the Lock object used for?
Thread.join is used to wait for another thread to finish. The join method uses the implicit lock on the Thread object and calls wait on it. When the thread being waited for finishes it notifies the waiting thread so it can stop waiting.
Java has different ways to use locks to protect access to data. There is implicit locking that uses a lock built into every Java object (this is where the synchronized keyword comes in), and then there are explicit Lock objects. Both of them protect data from concurrent access, the difference is the explicit Locks are more flexible and powerful, while implicit locking is designed to be easier to use.
With implicit locks, for instance, I can't not release the lock at the end of a synchronized method or block, the JVM makes sure that the lock gets released as the thread leaves. But programming with implicit locks can be limiting. For instance, there aren't separate condition objects so if there are different threads accessing a shared object for different things, notifying only a subset of them is not possible.
With explicit Locks you get separate condition objects and can notify only those threads waiting on a particular condition (producers might wait on one condition while consumers wait on another, see the ArrayBlockingQueue class for an example), and you can implement more involved kinds of patterns, like hand-over-hand locking. But you need to be much more careful, because the extra features introduce complications, and releasing the lock is up to you.
Locking typically prevents more than one thread from running a block of code at the same time. This is because only ONE thread at a time can acquire the lock and run the code within. If a thread wants the lock but it is already taken, then that thread goes into a wait state until the lock is released. If you have many threads waiting for the lock to be released, which one gets the lock next is INDETERMINATE (can't be predicted). This can lead to "thread starvation" where a thread is waiting for the lock, but it just never gets it because other threads always seem to get it instead. This is a very generic answer because you didn't specify a language. Some languages may differ slightly in that they might have a determinate method of deciding who gets the lock next.
In Java, a thread can go to sleep so that it won't hog the process and other thread can get chance to run. This is done by calling sleep().
However, different from calling wait(), the thread, after calling sleep(), will NOT release the lock it's been holding. Since this thread is still holding the lock, how can other thread get chance to run while not being able to get the unreleased lock?
They can't; other threads that need to acquire a lock held by a sleeping thread will block until they can get it. There's no way to back off like tryacquire on explicit Locks, so the threads are stuck.
Threads shouldn't sleep while holding a lock. If a thread isn't doing something useful it doesn't need to be holding a lock.
To go dormant and release a lock use the wait method. Sleep doesn't have any means to cut its sleep time short other than interruption (which should be used for cancellation), wait lets the thread be notified.
If you call Thread.sleep() while holding a lock or from inside a synchronized block/method, any other threads that reach that lock will wait until the first thread resumes and releases the lock.
However locks/synchronization are not global, any threads that don't reach the locks held by the sleeping thread can run without issue.
If other thread can't get the lock to run while this thread is going to sleep, then what's the purpose for this thread to go sleep at first place?
The only person who can answer that question is the person who wrote the code that runs in the thread.
Was that you?
As Nathan Hughes said, it practically never is a good idea for a thread to sleep() while holding a mutex lock. To take that idea a little further: It almost never is a good idea for a thread to do anything that takes more than a microsecond or so while holding a mutex lock. If you find yourself writing code that waits for something while keeping a lock locked, then that's a sign that you might need to re-think the architecture.
Also, there are not many good reasons for calling sleep() at all.
In Java, a thread can go to sleep so that it won't hog the process and other thread can get chance to run.
That's not really what sleep() is for. In most cases, when a thread doesn't need the CPU, it will block in a wait() call or in some xyz.await() call (where xyz is a queue or a semaphore or a latch or some other higher-level synchronization object).
The sleep() function is a low-level, primitive that your program can call in order to meet real-time requirements. But most programs with real-time requirements can make use of higher-level facilities such as java.util.concurrent.ScheduledThreadPoolExecutor
or javax.swing.Timer. If you start by writing your own sleep() calls, without first investigating the higher-level objects, then you may be re-inventing a wheel.
The JDK Documentation kind of mentioned it,
If the current thread is interrupted by any thread before or while it is waiting, then an > InterruptedException is thrown. This exception is not thrown until the lock status of this >object has been restored as described above.
I just want to be absolutely certain that the use of word "restored" means the lock must be released and reacquired, instead of being hold continuously by the thread calling Object.wait(). In other words, there is a chance that the lock is granted to other threads first.
I just want to be absolutely certain that the use of word "restored" means the lock must be released and reacquired, instead of being hold continuously by the thread calling Object.wait(). In other words, there is a chance that the lock is granted to other threads first.
There is never a guaranty that the lock is granted to other threads first. Even if the thread releases the lock and re-acquires it afterwards, it might succeed in re-acquiring the lock before any other thread waiting for the same lock gets a chance.
An implementation might allow bypassing the release and re-acquire of the lock in case of an early thread interruption and it might do so even without interruption in the case of a spurious wakeup that the specification allows to occur.
In other words, when wait ends, regardless of normally or exceptionally, there is no guaranty that any other thread has been run.
The documentation clearly says:
A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup. While this will rarely occur in practice, applications must guard against it by testing for the condition that should have caused the thread to be awakened, and continuing to wait if the condition is not satisfied. In other words, waits should always occur in loops, like this one:
synchronized (obj) {
while (<condition does not hold>)
obj.wait(timeout);
... // Perform action appropriate to condition
}
This also hold for the case that an InterruptionException has been thrown. When following this general rule of how to use the intrinsic locking, your question becomes irrelevant: if one thread keeps waiting while the condition does not hold, other threads which do not wait for this condition (or are responsible for establishing the condition) will eventually run.
I'm just trying to further my understanding of this concept.
We have a monitor, let's say a queue or a map of some sort. This monitor has methods to put objects on, and get objects off. In order to be thread safe, the monitor will lock on it's put methods and on it's get methods. When a thread is synchronized to this monitor, it's constantly trying to obtain this monitor's right's so it can proceed with what it needs to do. Does this sound right?
Another question, how does the flow of control work here. Which code is executed once the thread has gained access to the monitor? I'm finding it hard to debug multi-threaded programs with just print statements, it get's really messy and confusing.
public void run(){
try{
synchronized (monitor){
while (monitor is empty){
monitor.wait(); // Does this line pause the thread or the monitor?
}
System.out.println("Done Waiting");
}
System.out.println("Out of the synchronized block");
}
}
Here's the definition from the Java Language Specification:
The Java programming language provides multiple mechanisms for
communicating between threads. The most basic of these methods is
synchronization, which is implemented using monitors. Each object in
Java is associated with a monitor, which a thread can lock or unlock.
Only one thread at a time may hold a lock on a monitor. Any other
threads attempting to lock that monitor are blocked until they can
obtain a lock on that monitor. A thread t may lock a particular
monitor multiple times; each unlock reverses the effect of one lock
operation.
To answer
This monitor has methods to put objects on, and get objects off. In
order to be thread safe, the monitor will lock on it's put methods and
on it's get methods. When a thread is synchronized to this monitor,
it's constantly trying to obtain this monitor's right's so it can
proceed with what it needs to do. Does this sound right?
So you're not interacting with a monitor. A monitor doesn't have a concept of methods. Don't think of it like that. You interact with objects which have monitors. When a thread acquires an object's monitor, it doesn't need to constantly trying to obtain it, it already has it.
Another question, how does the flow of control work here. Which code
is executed once the thread has gained access to the monitor? I'm
finding it hard to debug multi-threaded programs with just print
statements, it get's really messy and confusing.
If execution enters the synchronized block on an object, the currently executing thread has acquired the monitor on the synchronized object, in this case the object referenced by the variable monitor.
I'll assume (thanks to Radiodeaf) that by monitor is empty, you mean your Map object doesn't have any entries.
When you call
monitor.wait();
the current thread releases the monitor on the object referenced by monitor and sleeps until it gets notified.
The javadoc of Object#wait() has more details.
So you will loop on the check for empty and wait if it returns true. We can assume that some other piece of code calls notify() when they put something into the Map.
When the object does get notified, the thread then has to compete to re-acquire the object's monitor. This is obviously necessary so that the thread can be executing inside a synchronized block on the object.
As we know We can call wait method only from synchronized context.
So By saying wait release the lock we mean that once lock is acquired on an object when it is in synchronized context , by calling wait method on same object , it release the lock and allow other thread to work on that object.
I am creating a multiple threads and calling yield() inside it.
The java.lang.Thread.yield() method causes the currently executing thread object to temporarily pause and allow other threads to execute.
Will It be possible for other threads to execute which also want to go inside synchronized block?
synchronized(this.lock)
{
//calling yield here.
}
thanks.
As far as I know, Yield() only gives up the remaining time slice on the CPU and steps back in the queue. It doesn't release any synchronized objects.
yield does not take or release locks, it simply pauses the current thread execution. So yielding in the synchronized block will not let the current thread to release lock and let the other methods to enter the synchronized block. wait/notify method should be used to release the lock.
From Java Language Specification
Thread.sleep causes the currently executing thread to sleep
(temporarily cease execution) for the specified duration, subject to
the precision and accuracy of system timers and schedulers. The thread
does not lose ownership of any monitors, and resumption of execution
will depend on scheduling and the availability of processors on which
to execute the thread.
It is important to note that neither Thread.sleep nor Thread.yield have any synchronization semantics. In particular, the compiler does
not have to flush writes cached in registers out to shared memory
before a call to Thread.sleep or Thread.yield, nor does the compiler
have to reload values cached in registers after a call to Thread.sleep
or Thread.yield.
yield allows a context switch to other threads, so this thread will not consume the entire CPU usage of the process. The thread still holds the lock. It is the developer responsibility to take care of deadlocks.