/* The basic Java synchronization mechanism centers on the keyword "synchronized", which predicates methods. In java, all objects can be used like monitors (protected types). However, it is necessary that you understand the precise meaning of the keyword. Axiom: Given object A, no more than one thread can execute a synchronized method of A at any time. Note that this does NOT mean: i: a synchronized and a non-synchronized method can't be concurrently executed by different threads ii: if A and B are distinct objects, their synchronized methods cannot be executed concurrently. "Synchronized" is relative to object, not thread. A thread in java is any object of a class that implements the interface Runnable. This means that there's a public void run() method in the class. However, PLEASE PLEASE PLEASE do not confuse a thread object with a synchronization object. A synchronization object, with "synchronized" methods, is like an Ada protected type object with entries. It is itself not a thread. Methods you can call: this : pointer to current object (as you should know) Thread.currentThread() : pointer to currently executing THREAD object. These are (usually) NOT the same! (see example whatsthis.java). Inside a synchronized method, you can call wait(), notify() and notifyAll(). These methods all can throw InterruptedException. wait() will immediately cause a thread to suspend execution, and at the SAME TIME, release its hold on the synchronization object. When another thread calls notify() or notifyAll() on the same synchronization object, the thread(s) that have called wait will be woken up and put back on the ready-to-run queue. The following example and comments further illustrate the potential subtleties of Java that can confuse you if you don't think carefully. */ /////////////// Simple Barrier Mechanism in Java public class barrier { public synchronized void block() throws InterruptedException { wait(); } public synchronized void release() throws InterruptedException { notify(); } public synchronized void releaseAll() throws InterruptedException { notifyAll(); } } // barrier. /* ****************************** Points to understand carefully: 1. Two threads in Java can synchronize using a shared barrier object as follows (see usebarrier.java for full example): Assume barrier BR is shared between the two threads thread1: thread2: ... ... BR.wait(); ... BR.release(); ... 2. The natural question you probably have at this point is, why not just have the threads call wait(), notify() and notifyAll() directly? Why define new functions when all they do is call these built-ins? This is a very important point to understand. Java's synchronization mechanisms are centered on objects, not threads. The word "synchronized" means that no two threads can be calling a synchronized method of an *object* at the same time. Now, thread1 and thread2 are also objects (of the class Thread). Let's say thread1 were to call wait() directly. IT WOULD BE BLOCKING ON ITSELF! If thread2 then calls notify() directly, it would only release a thread that has called wait() on the thread2 object. But thread1 did not call wait on thread2, it called it on itself. So thread1 will stay blocked. A method can belong to object thread1, but it can be executed by thread2. If thread2 calls thread1.block, it will be blocked on thread1's waiting queue. THINK THIS THROUGH PLEASE. The purpose of the barrier class, with its seemingly redundant functions, is to be able to create barrier objects. Both thread1 and thread2 can then synchronize on a shared barrier object. The call to wait() inside the block() method of such an object will cause a thread to block on the shared object. Then, when thread2 calls release() or releaseAll() ON THE SAME OBJECT, it will release the thread that is waiting on this object. To put it yet another way, when wait is called from block(), it is is really calling this.wait() and when notify() is called from release(), it is really calling this.notify(). You must ask yourself: what does "this" refer to? The "this" object that the wait() and notify() calls are made on MUST BE THE SAME in order for there to be synchronization. Please do not become content with just a vague understanding of what I've said. That would be even worse than not knowing anything. 3. One final point before we look at more sophisticated mechanisms is that the barrier class is not the same as a semaphore or mutex. When a thread calls lock() on a mutex, it does not block unless some value is set to false or zero. However, calling block() on a barrier will ALWAYS cause a thread to block. Mutexes and semaphores can also be defined, however, by using the wait()/notify() mechanism in a different arrangement. See the next example (mutexes.java). */