Sorry for making stupid program but this shows how 2 threads can call 2 different synchronized methods at the same time(for the same object).
Their are two threads producer and consumer , both takes Factory as the common object, so that they can call methods on this object at the same time.
The output of the program would be alternate produce and consume..(it nevers stops)..press ctrl+c to stop the main thread.
class Factory
{
int a = 0;
synchronized public void produce()
{
try
{
notify();
System.out.println("produce");
wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
synchronized public void consume()
{
notify();
System.out.println("consume");
try
{
wait();
}
catch (InterruptedException e1)
{
e1.printStackTrace();
}
}
}
class Producer extends Thread
{
//common object. whose methods will be called
Factory f1;
public Producer(Factory f1)
{
this.f1 = f1;
}
public void run()
{
produce();
}
public void produce()
{
while (true)
{
f1.produce();
}
}
}
class Consumer extends Thread
{
Factory f1;
public Consumer(Factory f1)
{
this.f1 = f1;
}
public void run()
{
consume();
}
public void consume()
{
while (true)
{
f1.consume();
}
}
}
public class TestThread
{
/**
* @param args
*/
public static void main(String args[])
{
Factory f1 = new Factory();
Consumer consumer = new Consumer(f1);
Producer producer = new Producer(f1);
consumer.start();
try
{
Thread.sleep(100);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
producer.start();
}
}
In order to call a synchronized method on an object you must first acquire that object's monitor lock. Only one thread can hold the lock for an object at a given time.
Lets say you have only two threads, T1 and T2, and you call a synchronized method from T1, T1 will now obtain the lock and execute the method. Now if you try and call another synchronized method from T2, it will try to obtain the lock but will have to wait until T1 releases it. When T1 finishes executing the method it exits the synchronized block and releases the lock. T2 can now execute its method.
Another way for T1 to release the lock would be to call the object's wait method. This causes T1 to wait on that object's notify queue. When it has been notified it will need to re-obtain the lock before it can continue.
So, to summarize, synchronized methods require the caller to have the lock on that object. To execute any synchronized method the lock must be obtained, and only one Thread can have this at any one time.
> In order to call a synchronized method on an object
> you must first acquire that object's monitor lock.
No, the thread must acquire the lock. It is automatic.
> Another way for T1 to release the lock would be to
> call the object's wait method. This causes T1
> to wait on that object's notify queue.
It's not a queue, it's just an unordered collection really.
> When it has
> been notified it will need to re-obtain the lock
> before it can continue.
Again this is automatic.
> So, to summarize, synchronized methods require the
> caller to have the lock on that object.
.. require the calling thread to obtain the lock, which is automatic.
> To execute any synchronized method the lock must be obtained,
> and only one Thread can have this at any one time.
You keep making it sound like something the caller has to do. For a synchronized method this is all automatic.
You're right I was a bit unclear about it. I just wanted to get the point across about what had to happen, automatic or not, because these are the concepts behind synchronization. I tried to imply that the thread obtains these locks automatically with this: "T1 will now obtain the lock".
> It's not a queue, it's just an unordered collection really.
thanks for the info, didn't know that. So when notify is called is it an arbitrary waiting thread that is notified?
Yes. That's why it's usual to use notifyAll() and while (!condition) wait(); - it tends to have the effect that the highest priority thread gets the lock, which is otherwise not guaranteed. A queue would be able to guarantee those semantics (or any others such as FIFO) easily. Semantics borrowed from the Unix kernel.