Difference between Locks and .join() method - java

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.

Related

How deterministic are Java semaphores guaranteed to be?

The (Oracle) javadoc for Semaphore.release() includes:
If any threads are trying to acquire a permit, then one is selected and given the permit that was just released.
Is this a hard promise? This implies that if thread A is waiting in acquire() and thread B does this:
sem.release()
sem.acquire()
Then the release() should pass control to A and B will be blocked in acquire(). If these are the only two threads that can hold the semaphore and the doc statement is formally true, then this is a completely deterministic process: Afterward, A will have the permit and B will be blocked.
But this is not true, or at least it does seem that way to me. I haven't bothered with an SSCCE here since I am really just looking for confirmation that:
Race conditions apply: Even though thread A is waiting on the permit, when it is released it can be immediately re-acquired by thread B, leaving thread A still blocked.
These are "fair" semaphores if that makes any difference, and I'm actually working in kotlin.
In comments on the question Slaw pointed out something else from the documentation:
When fairness is set true, the semaphore guarantees that threads invoking any of the acquire methods are selected to obtain permits in the order in which their invocation of those methods was processed (first-in-first-out; FIFO). Note that FIFO ordering necessarily applies to specific internal points of execution within these methods. So, it is possible for one thread to invoke acquire before another, but reach the ordering point after the other, and similarly upon return from the method.
The point here is that acquire() is an interruptable function with a beginning and an end. At some point during its exception the calling thread secures a spot in the fairness queue, but when that is in relation to another thread concurrently accessing the same function is still indeterminate. Call this point X and consider two threads, one of which holds the semaphore. At some point another thread calls:
sem.acquire()
There is no guarantee that the scheduler won't sideline the thread inside acquire() before point X is reached. If the owner thread then does this (this could be, eg., intended as some kind of synchronization checkpoint or barrier control):
sem.release()
sem.acquire()
It could simply release and acquire the semaphore without it being acquired by another thread even if that thread has already entered acquire.
The injection of Thread.sleep() or yield() between the calls might often work, but it is not a guarantee. To create such a checkpoint with that guarantee you need two locks/semaphores for an exchange:
Owner thread holds semA.
Client thread can take semB and then wait on semA.
Owner can release semA then wait on semB, which if another thread is really waiting for semA by holding semB, will block and guarantee semA can now be acquired by the client.
When the client is done, it releases semB, then semA.
When the owner is released from waiting on semB, it can acquire semA and release semB.
If these are properly encapsulated this mechanism is rock solid.

In Java, how can other thread get chance to run after current thread is called on sleep() but still holds the lock?

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.

wait() , notify() - which thread first unlock?

Trying to understand wait() and notify(). I know when thread A went to wait() it will be waked up by notify() from other thread.
But what will happens if threads A,B,C went to wait() in represented order? Who will be waked up by notify()? According to my experiments A thread will be waked up at first. I'm right?
Does it means that system knows in which order threads went to wait() ?
From the documentation for notify(), emphasis mine:
Wakes up a single thread that is waiting on this object's monitor. If any threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation. A thread waits on an object's monitor by calling one of the wait methods.
Some other APIs, such as Semaphore, have a concept of "fairness", where you can ensure that threads do proceed in the order in which they blocked.
Section 17.2.2 Notification of Java Language Specification:
There is no guarantee about which thread in the wait set is selected.
So, observed behavior is not guaranteed and should not be relied upon.
No, the VM does not know in which order the threads were put in Waiting state.
When you call notify(), one of them will be back to Alive/Runnable state and there is no way to know which one the VM will choose.
Sometimes they can run in the order they were put in Waiting state, but the specification does not guarantee that. So in a different VMs you can have a completely different results or even in the same VM, if you run the code multiple times.
No, there is no guarantee about the order. The javadoc of the notify method is pretty clear on this:
Wakes up a single thread that is waiting on this object's monitor. If any threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation. A thread waits on an object's monitor by calling one of the wait methods.
There's no such an order. Either thread has an equal opportunity to get into runnable state. Actually JVM/OS can see them only as a set of waiting threads, they don't know any order.
In terms of your experiment, to get into a fair conclusion, actually you have to perform it for a huge number of times.
In threads, you can expect an order (FIFO), only if you are using something like a strong Semaphore. Then these threads are put into a waiting queue and fist comer would be first served.

locking synchronization in java using reentrant lock

I have and application made in java that uses an reentrant global lock and I have a problem like this:
One thread is acquire the reentrant global lock and let say that is keeping the lock 30 seconds in this interval of time it makes some operations. In this interval of time all other threads are blocked.
My problem is that I want some threads like RMI to have the chance to execute.
What would be a good locking policy or optimization in order to let some other threads to acquire the lock for a short period of time ?
So you basically have a job queue which should be executed in a single-threaded environent. Each time before polling from this queue you need to sort it's entries by priority.
abstract class JobEntry<V> implements Callable<V>{
Date registeredAt;
long runEstimationMs;
JobType type;
}
So you could come up with a weighing function for this entry and sort entries based on it or with implementing Comparable.
And this is almost it. You could send these jobs to a fixed thread pool of a single thread. If you need to interrupt them, you would need to cancel the future and each job should check Thread.interrupted() state.
The most difficult part here is the weighing function, a possible way to build it could be making a set of experiments on your system.
If one thread has acquired lock other threads cant proceed , we can not change this behavior.
Now to solve your problem there are few suggestions I want to give.
Try to Reduce lock scope so that other threads also get chance for execution.
Look at the possibility if you can acquire lock for really required part and release lock after that. Because as you said one thread is taking good amount of time there could be some part of code where you don't need locking.
operationInLock(){
----
lock.lock();
Code where lock is required;
lock.unlock();
Code where lock is Not required;
Code where lock is Not required;
Code where lock is Not required;
lock.lock();
Code where lock is required;
lock.unlock();
Code where lock is Not required;
Code where lock is Not required;
Code where lock is Not required;
}
If you don't feel this answer useful , give us some more info about code/functionality because without seeing code it becomes very difficult to give solution we can just give u suggestions based on best practice.
I believe this can be achieved via acquiring on only particular section of code by first thread which has global lock for 30 seconds and also you can also use Read and write separate locks which comes with ReadWriteLock Object in java.
ReadWriteLock is implemented by ReentrantReadWriteLock Class in java.util.concurrent.locks package.Multiple Threads can acquire multiple read Locks, but only a single Thread can acquire mutually-exclusive write Lock .Other threads requesting readLocks have to wait till the write Lock is released. A thread is allowed to degrade from write lock to read lock but not vice-versa. Allowing a read thread to upgrade would lead to a deadlock as more than one thread can try to upgrade its lock. The ReentrantReadWriteLock also supports all the features of the Reentrant lock like providing the fair mechanism, reentrant locks, Condition Support (on a write Lock only), allowing interruption on read as well as write Locks.
. A Condition object, also known as condition variable, provides a thread with the ability to suspend its execution, until the condition is true. A Condition object is necessarily bound to a Lock and can be obtained using the newCondition() method.
Furthermore, a Condition enables the effect of having multiple wait-sets per object, by combining these sets with the use of a Lock implementation. Moreover, due to the fact that Conditions access portions of state shared among different threads, the usage of a Lock is mandatory. It is important to mention that a Condition must atomically release the associated Lock and suspend the current’s thread execution.
For your reference I am giving you the URLs ->
https://examples.javacodegeeks.com/core-java/util/concurrent/locks-concurrent/condition/java-util-concurrent-locks-condition-example/
https://examples.javacodegeeks.com/core-java/util/concurrent/locks-concurrent/readwritelock/java-readwritelock-example/
Please let me know if you need other help

Does thread.yield() lose the lock on object if called inside a synchronized method?

I understand that Thread.currentThread().yield() is a notification to thread scheduler that it may assign cpu cycle to some other thread of same priority if any such is present.
My question is: If current thread has got lock on some object and calls yield(), will it loses that lock right away? And when thread scheduler finds out there is no such thread to assign cpu cycle, then the thread which has called yield() will again be in fight to get lock on the object which it has lost earlier??
I couldn't find it in javadoc and forums [http://www.coderanch.com/t/226223/java-programmer-SCJP/certification/does-sleep-yield-release-lock] have 50-50 answers.
I think yield() (lets say thread1) should release lock because if some thread (lets say thread2) of same priority wants to operate on same object, then it can have chance when thread scheduler eventually assign cup to thread2.
No. Thread.yield() is not like Object.wait(). It just gives up control to allow a thread switch. It will have no effect on the concurrency of your program.
There is no guarantee which thread the scheduler will run after a yield.
In Java Language specification
17.3 Sleep and Yield
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.
My comment:
In java's early days, when it did not really supported parallel executions, but only concurrent (green threads), yield() was suspending the current thread, and the jvm was picking up another thread to resume. Now-days, yield does not have much meaning as usually the tread scheduling is on OS level.
So, yield is just a hint to the JVM that current thread wants to take a rest and nothing else, it is up to the thread scheduler to decide what to do. yield does not have any synchronization semantic. If thread holds lock, it will continue to hold it.
Only wait methods of the Object class release the intrinsic lock of the current instance (the thread may have other locks acquired, they don't get released). Yield, sleep, join do not bother about locks. However, join is a little more special, you are guaranteed to see all the changes made by the thread you're waiting for to finish.

Categories