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.
Related
I came across the following e example to implement custom suspend and wait from some website.
// Suspending and resuming a thread the modern way.
class NewThread implements Runnable {
String name; // name of thread
Thread t;
boolean suspendFlag;
NewThread(String threadname) {
name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
suspendFlag = false;
t.start(); // Start the thread
}
// This is the entry point for thread.
public void run() {
try {
for (int i = 15; i > 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(200);
synchronized(this) {
while (suspendFlag) {
wait();
}
}
}
} catch (InterruptedException e) {
System.out.println(name + " interrupted.");
}
System.out.println(name + " exiting.");
}
void mysuspend() {
suspendFlag = true;
}
synchronized void myresume() {
suspendFlag = false;
notify();
}
}
class SuspendResume {
public static void main(String args[]) {
NewThread ob1 = new NewThread("One");
NewThread ob2 = new NewThread("Two");
try {
Thread.sleep(1000);
ob1.mysuspend();
System.out.println("Suspending thread One");
Thread.sleep(1000);
ob1.myresume();
...................
I am more concerned about the ob1.mysuspend() and ob1.myresume() calls. When my suspend is called then ob1 will be placed into the blocking queue associated with the runnable object it is using. When ob1 calls myresume, then how does it work as ob1 is already in waiting queue for the same object, can the waiting object enters another synchronised method and then signals notify to itself?How does this work?What am I missing?
The thread is written so that while an instance of NewThread is running, another thread can call mysuspend to suspend that running thread. Again, a thread other than the suspended thread calls myresume to resume the suspended thread.
There also appears to be a data race because mysuspend writes to suspendFlag without any synchronization. That means, the thread that needs to be suspended may not see that write immediately. mysuspend must be declared synchronized, or suspendFlag must be volatile.
This code is flat out broken.
Straight up broken: JMM violation
The mysuspend method (which should be named mySuspend, by the way) updates a field that is then read from another thread, and isn't synchronized. This is an error - and a really nasty one because you cannot reliably test that it is an error. The Java Memory Model (JMM) states that any write to a field may be observable or not, at the discretion of the JVM implementation, unless a so-called Happens-Before/Happens-After relationship is established (there are many ways to do it; usually you do so via synchronized, volatile, or some other concurrency tool built on these primitives, such as the latches and queues in the java.util.concurrent package).
You do not establish such a relationship here, meaning, that suspendFlag = true results in a schroedingers cat variable: The other thread that reads this field may read true or false, the JVM gets to decide what you see. Hence: A bug, and, untestable. bad. Any field that is read/written to by multiple threads needs to be written extremely carefully.
Mark that method synchronized, that's a good first step.
Wait and Notify
You've got it flipped around: You must in fact hold the synchronized lock on x when you invoke wait on x (here, x is this).
To call x.wait() (you are calling this.wait(), effectively), you must first be in a synchronized(x) block. Once the wait 'goes through', the code releases the lock (other synchronized(x) blocks can run). To invoke x.notify() you must also hold that lock.
wait does not return until the lock is re-established.
In other words:
public void foo() {
wait();
}
will fail at runtime. Try it. Guaranteed exception. In the mean time, this:
public void foo() {
synchronized (this) {
// code before wait
wait();
// code after wait
}
}
is executed as if it is written like this:
public void foo() {
synchronized (this) {
// code before wait
release_lock(this);
this.wait();
acquire_lock(this);
// code after wait
}
}
Where acquire_lock is guaranteed to actually take a while (because by definition whatever invoked notify() to wake you up is currently holding it! So wait is always a two-hit thing: You need to be both notified AND the lock needs to be reacquired before your code will continue). Except, of course, acquire_lock and release_lock don't exist, and unlike this hypothetical code, wait() is more atomic than that.
I'm trying to figure out how to use wait & notify, so I've written this small example with a few planes waiting for a runway to clear before they take off, the issue I'm having is that when a plane takes off, and calls notifyAll(), only one thread seems to be woken up, i.e. I expect all of the threads to report that they have been notified, but are still waiting. What actually happens is that only one thread is woken, and the rest do nothing. Why does it appear that only the one thread is woken, and how can I fix it?
class Plane extends Thread
{
Runway runway;
Plane(int id, Runway runway)
{
super(id + "");
this.runway = runway;
}
public void run()
{
runway.taxi();
runway.takeoff();
}
}
class Runway
{
boolean isFull;
Runway()
{
isFull = false;;
}
public synchronized void taxi()
{
System.out.println(Thread.currentThread().getName() + " started to taxi");
while(isFull)
{
System.out.println(Thread.currentThread().getName() + " is queued");
try
{
wait();
}
catch(InterruptedException e){}
}
isFull = true;
System.out.println(Thread.currentThread().getName() + " entering runway");
}
public synchronized void takeoff()
{
try
{
Thread.currentThread().sleep(1000);
}
catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName() + " took off");
isFull = false;
notifyAll();
}
public static void main(String[] args)
{
Runway runway = new Runway();
new Plane(1, runway).start();
new Plane(2, runway).start();
new Plane(3, runway).start();
new Plane(4, runway).start();
}
}
Thanks for taking the time to help me :)
Because notifyAll() is not wakeAll(). All threads are notified, but only one gets hold of the key and is being run. All others get to waiting pull again.
Suppose you have 4 Planes that are all start()-ed one after the other.
All 4 will attempt to call taxi() followed by takeoff()
The first one will call taxi():
acquire the lock,
find isFull is false
set isFull to true
return, releasing the lock
Then one (or more) of the remaining threads may get to call taxi(). If they do, they:
acquire the lock
find isFull is false
call wait() which releases the lock
OR
block while trying to acquire the lock
In the mean time, the thread that returned from taxi() will call takeoff(). This will:
acquire the lock
sleep for 1 second,
notify any threads that were waiting
return, releasing the lock.
So how does this explain what you are seeing?
Suppose that when the first thread returned from taxi() it was immediately able to reacquire the lock and start the takeoff() call. It would then call sleep() WHILE HOLDING THE LOCK. This would prevent any other threads from starting their taxi() calls (if they hadn't already done so). Then after the sleep, it would call notifyAll(). But that would only notify the threads that were had gotten into the taxi() call and that had called wait(). Any threads that were blocked while starting the taxi() call would never see the notifications.
(Notifications are never queued for threads that are not in wait() calls.)
Is this likely? Well yes it is.
Starting a thread is a relatively expensive / time consuming process, and there is a good chance that the first thread started will get to do a lot of work before the next one gets started. The chances are that it will get all the way to the sleep call before the second one tries to call taxi().
The same pattern is likely to repeat for the remaining threads. When each thread that gets into taxi() is likely to release and then reacquire it before another thread is scheduled. (Thread scheduling is handled by the OS, and it is optimizing for efficiency rather than fairness. If you want fair scheduling, you need to use a Lock object.)
... how can a fix it?
Change your code so that you don't sleep while holding the lock. For example:
public void takeoff() {
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
// squash ...
}
System.out.println(Thread.currentThread().getName() + " took off");
synchronize (this) {
isFull = false;
notifyAll();
}
}
That's what it does. It "notifies" all the waiting threads, but only one wakes and gets the CPU. notify() picks a waiting thread based on what the underlying thread implementation selects. notifyAll() gives all the waiting threads an equal chance to compete. But either way, only one thread takes the context.
This question was asked to me in an interview. Before I had told him this,
Once a thread enters any synchronized method on an instance, no other
thread can enter any other synchronized method on the same instance.
Consider the snippet:
Q1:
public class Q1 {
int n;
boolean valueSet = false;
synchronized int get() {
while (!valueSet)
try {
wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
System.out.println("Got: " + n);
valueSet = false;
notify();
return n;
}
synchronized void put(int n) {
while (valueSet)
try {
wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
this.n = n;
valueSet = true;
System.out.println("Put: " + n);
notify();
}
}
Producer1:
public class Producer1 implements Runnable {
Q1 q;
Producer1(Q1 q) {
this.q = q;
new Thread(this, "Producer").start();
}
#Override
public void run() {
int i = 0;
while (true) {
q.put(i++);
}
}
}
Consumer1
public class Consumer1 implements Runnable {
Q1 q;
Consumer1(Q1 q) {
this.q = q;
new Thread(this, "Consumer").start();
}
#Override
public void run() {
while (true) {
q.get();
}
}
}
PC1:
public class PC1 {
public static void main(String args[]) {
Q1 q = new Q1();
new Producer1(q);
new Consumer1(q);
System.out.println("Press Control-C to stop.");
}
}
So, he asked as soon as you have created this thread new Producer1(q), then according to you, the synchronized int get() method must have been locked by the same thread, i.e, by new Producer1(q) when it accessed synchronized int put(). I said yes.
But I checked in eclipse, get is callable by new Consumer1(q). The program works perfect.
Where am I going wrong?
O/P:
The call to wait() will release the monitor for the time waiting.
That's what is documented for Object.wait():
The current thread must own this object's monitor. The thread
releases ownership of this monitor and waits until another thread
notifies threads waiting on this object's monitor to wake up
either through a call to the notify method or the
notifyAll method. The thread then waits until it can
re-obtain ownership of the monitor and resumes execution.
Once a thread enters any synchronized method on an instance, no other
thread can enter any other synchronized method on the same instance.
What you forgot to add here is "except if the lock is released".
...and it is the case in your example, when calling wait.
The documentation specify :
The thread releases ownership of this monitor and waits until another
thread notifies threads waiting on this object's monitor to wake up
either through a call to the notify method or the notifyAll method.
Since the lock is released, you step in the other method (and the condition is true because the boolean was modified). Once in the other method, you release the lock again, then call notify and you wake up the old thread which terminates (re-modify boolean to pass the condition in other method, and notify). That way you step between both methods ad-infinitum.
wait() and notify() is acts as a signal between threads, to control the threads to do or to not do the stuff.
The program works perfect because here 2 threads (Producer, Consumer) which fight for the one lock (monitor). When Consumer aquires the lock (Q1 object) then Producer is waiting for the lock. When Consumer finishes his work it release the lock. Consumer releases the lock also when wait() method has been called, because wait() sets thread to Waiting state with lock release. It's time for Producer to aquire the lock and does his work. When Producer thread notify() calls then Consumer continue his work (when aquired the lock). The same is right for Producer.
Resume: Q1 object is a lock for all threads. If it aquired someone then others are blocked and the answer is - it not possible to get an access at the same time to the get(), put() methods more then 2 threads.
I think that the question is ambiguous. (E.g., what does "accessible" mean?)
IMO, a good interview question should not have a right answer and a wrong answer. A good interview question should be a conversation starter, that gives you an opportunity to show how much you know about the subject.
When I am asking the interview questions, I like a candidate who can see through the question, and get down to the underlying mechanism. E.g.,
What the JLS guarantees is that no two threads can be _synchronized_
on the same instance at the same time...
Then we could explore questions like, how could two threads enter the same synchronized method at the same time? (e.g., synchronized on different instances), how could two threads be in the same synchronized method for the same instance at the same time (one of them could be in a wait() call), ...
A thread can not access a synchronized block of code unless it has aquired a lock on the object that guards the block. In your case, the synchronized keyword uses the lock of the object in which it has been declared. So as long as a thread is executing get(), no other thread can execute the put().
If you apply this, when put() sets the value, it notifies consumer which accepts the value. The code should work even after you have removed the wait() and notify() calls from both get and put methods
I was just curious is it possible that a thread T1 say executes a synchronization block partially and then releases the lock on the object and another thread T2 executes the same block? Something like this:
line1: synchronized(this){
line2: if(INSTANCE == null)
line3: INSTANCE = new Object(); //say a variable is initialized
line4: return INSTANCE;
line5: }
Is it possible that thread T1 acquires a lock on current object (this) and executes line1 and line2. Then thread T1 is preempted by thread T2, T1 releases lock and T2 acquires lock on this and executes the same block (all the lines1 to 5). Then thread T1 again takes the lock and continues executing from line3?
Basically, T1 will see INSTANCE as null and so will T2 and each will create a new Object.
If this is not possible can someone explain why not?
Addendum:
Thanks everyone for your answer. My question was a bit misleading. What I am exactly asking, is it possible that once a thread is executing a synchronized block it can release the lock before the entire block is executed (not by explicitly calling wait() but something which is process, CPU dependent)? Is there a contract in JLS or a JVM guarantee that once a thread starts executing a synchronized block the lock on the object is not released until the end of the block? My understanding is synchronization guarantees no 2 threads can simultaneously execute the block (or other synchronized method/block) but the lock is hold until the end of the block is reached? It's kind of obvious but is it specified in the JLS?
Thread preemption doesn't cause the preempted thread to release its locks. If it did, locks would be worthless. The whole point of a synchronized block is that it will disallow other threads from synchronizing on the same object until the thread releases the lock (by leaving the synchronized block).
Even if a thread is preempted, it won't release a lock. The lock is still held. If another thread comes along, it will block (stop running) until the lock is released, even if the original thread gets preempted several times before it releases the lock. Basically almost any kind of lock has some storage in the heap that gets written to indicate there's a lock. It's permanent until the thread or the system writes a different value to indicate the lock is free.
It is of course possible to write code that allows access to an instance or field without ever taking the lock, but that's a coding error. It's also possible for the original thread to exit the block early (say it throws an exception) -- this releases the lock, and other threads can continue as normal.
I'm pretty sure it's not possible for a second thread to enter the synchronize block before the first one has executed the entire block. On obtaining the lock on the object, all other threads attempting to enter the synchronized code will be blocked.
See more information here: http://tutorials.jenkov.com/java-concurrency/synchronized.html
Basically you can use Locks objects. Lock objects can allow you to sequentially apply and release locks on multiple locks line by line.
A very good tutorial on how to implement it here
Check out below code:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class test2{
private static Object instance = null;
private static test2 t = new test2();
private static Lock lock = new ReentrantLock();
public static void main(String[] args) {
A a = new A();
B b = new B();
a.setName("Thread-A");
b.setName("Thread-B");
a.start();
b.start();
}
public Object getObj(){
try {
lock.lock();
System.out.println("Begin Current thread: "+ Thread.currentThread().getName());
if(instance == null){
if(Thread.currentThread().getName().equalsIgnoreCase("Thread-A")){
lock.unlock();
while(instance==null){
System.out.println(Thread.currentThread().getName() +" : instance is null");
}
while(true){
if(!lock.tryLock()){
System.out.println(Thread.currentThread().getName() + " waiting for re lock");
}else{
lock.lock();
break;
}
}
}
instance =new Object();
System.out.println("End Current thread: "+ Thread.currentThread().getName());
if (((ReentrantLock) lock).isHeldByCurrentThread()) {
lock.unlock();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return instance;
}
public static class A extends Thread{
#Override
public void run() {
while(true){
if(t.getObj() != null){
break;
}
}
}
}
public static class B extends Thread{
#Override
public void run() {
while(true){
if(t.getObj() != null){
break;
}
}
}
}
}
Output
Begin Current thread: Thread-A
Thread-A : instance is null
Begin Current thread: Thread-B
Thread-A : instance is null
End Current thread: Thread-B
Thread-A waiting for re lock
End Current thread: Thread-A
I wrote this program to check if a thread t1 holding lock on two different objects :
Lock.class and MyThread.class goes into waiting mode on MyThread.class instance using MyThread.class.wait().It does not release lock on Lock.class instance. why so ? I have been thinking that once a thread goes into wait mode or it dies it releases all the acquired locks.
public class Lock {
protected static volatile boolean STOP = true;
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
Thread t1 = new Thread(myThread);
t1.start();
while(STOP){
}
System.out.println("After while loop");
/*
*
*/
Thread.sleep(1000*60*2);
/*
* Main thread should be Blocked.
*/
System.out.println("now calling Check()-> perhaps i would be blocked. t1 is holding lock on class instance.");
check();
}
public static synchronized void check(){
System.out.println("inside Lock.check()");
String threadName = Thread.currentThread().getName();
System.out.println("inside Lock.Check() method : CurrrentThreadName : "+ threadName);
}
}
class MyThread implements Runnable{
public MyThread() {
}
#Override
public void run() {
try {
System.out.println("inside Mythread's run()");
classLocking();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static synchronized void classLocking() throws InterruptedException{
System.out.println("inside Mythread.classLocking()");
String threadName = Thread.currentThread().getName();
System.out.println("inside MyThread.classLocking() : CurrrentThreadName : "+ threadName);
/*
* outer class locking
*/
synchronized (Lock.class) {
System.out.println("I got lock on Lock.class definition");
Lock.STOP = false;
/*
* Outer class lock is not released. Lock on MyThread.class instance is released.
*/
MyThread.class.wait();
}
}
}
You are correct that it doesn't release the other lock. As for why, it's because it isn't safe to do so. If it was safe to release the outer lock during the call to the inner function, why would the inner function be called with the other lock held at all?
Having a function release a lock it didn't acquire behind the programmer's back would destroy the logic of synchronized functions.
Yes it is working correctly. A thread goes into waiting status releases the corresponding lock instead of all locks. Otherwise think about that: if things are like what you thought, then when a thread waits it loses all the acquired locks, which makes advanced sequential execution impossible.
The semantics of wait() is that the Thread invoking it notices that a lock was already acquired by another thread, gets suspended and waits to be notified by the thread holding the lock when the latter one releases it (and invokes notify). It doesn't mean that while waiting it releases all the locks acquired. You can see the wait's invocations as a number of barriers the thread meets on the way to acquiring all the locks it needs to accomplish an action.
Regarding the question "Why a thread doesn't release all the locks acquired when invoking wait" , I think the answer is that, doing so would make it more prone to starvation and it would also slow down the progress in a multithreaded application (All threads would give up all their locks when invoking the first wait and would have to start over when they acquire the lock they are currently waiting for. So, they would be in a permanent battle for locks.
Actually, in such a system, the only thread able to finish execution would be the one which manages to find all locks free when it needs them. This is unlikely to happen)
From JavaDoc of method wait()
The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.