[645] in java-interest
Re: Language issue: thread synchronisation
daemon@ATHENA.MIT.EDU (Chris Warth)
Mon Jul 10 21:04:58 1995
Date: Mon, 10 Jul 1995 11:10:41 -0700
From: csw@scndprsn.Eng.Sun.COM (Chris Warth)
To: lodge@houston.omnes.net
Cc: java-interest@java.Eng.Sun.COM
----------
X-Sun-Data-Type: text
X-Sun-Data-Description: text
X-Sun-Data-Name: text
X-Sun-Charset: us-ascii
X-Sun-Content-Lines: 47
>
> Serialising access to objects is one thing. However, it is not clear how
> two Java threads can synchronise their activities. Say one thread wants to
> wait for another to complete to reach a certain stage before continuing --
> how is that done efficiently (i.e. without doing polling) ?
>
> I am also worries by the phrase "condition variable paradigm". Does this
> mean there are semaphores in Java? Java avoids the usual C/C++ worries over
> dynamically allocated memory and so frees the programmer from a large
> number of typical programming errors. Semaphores are the concurrent
> programming equivalent of malloc(): good primitives, but extremely error
> prone to use -- there are much better synchronisation paradigms out there!
>
> A lot of water has passed under the concurrent programming bridge since
> Hoare's monitors and Djikstra's semaphores, and it would be a real shame if
> Java got stuck with error prone and unecessarily primitive synchronisation
> primitives.
>
There is a java language spec available from the documentation page
of the browser, but it doesn't say much if anything about how the runtime
behaves. I think the theory was we were going to cover that in a companion
document that is still to be written.
Anyway, to answer your question, monitors are not just for mutual
exclusion, they also include condition variables and so can be used for
synchronization as well.
Synchronizing two threads is just a slight variation on serializing
access to an object. All you have to do is consider one of the threads
to be the object whose access you want to serialize.
Consider the following code that synchronizes two independent threads.
In this example an instance of Consumer waits for a cookie from an
instance of Producer. The Producer and Consumer sleep for different
amounts of time to represent different computational loads. The
producer cannot give a new cookie to the consumer until it has
processed the last one, and the consumer cannot proceed until it
receives a new cookie from the producer.
Save the two attachments into files called Consumer.java and
Producer.java, respectively. Run javac on Consumer.java (which will
automatically compile Producer.java) and run "java Consumer".
There are thousands of way to code this sort of thing; multiple
producers, multiple consumers, synchronize on the consumer instead of
the producer, etc., but it all comes down to this simple example.
----------
X-Sun-Data-Type: default
X-Sun-Data-Description: default
X-Sun-Data-Name: Consumer.java
X-Sun-Charset: us-ascii
X-Sun-Content-Lines: 30
public class Consumer extends Thread {
private int lastcookie = 0;
private Producer prod;
public void setProducer(Producer p) {
prod = p;
}
public void run() {
while (lastcookie != 100) {
lastcookie = prod.waitForCookie();
System.out.println("Got a cookie #"+lastcookie);
sleep(100);
}
}
public static void main(String args[]) {
Consumer c = new Consumer();
Producer p = new Producer();
c.setProducer(p);
p.setConsumer(c);
c.start();
p.start();
}
}
----------
X-Sun-Data-Type: default
X-Sun-Data-Description: default
X-Sun-Data-Name: Producer.java
X-Sun-Charset: us-ascii
X-Sun-Content-Lines: 46
public class Producer extends Thread {
private int cookie = 0;
Consumer cons;
public void setConsumer(Consumer c) {
cons = c;
}
/*
* First notify the producer that we are ready for another
* cookie. The while loop is not strictly necessay. In fact it
* would be entirely eliminated from this example but it
* typcially found in more complex examples Lastly return the
* cookie. We do not reset the cookie to 0 until we next wait
* for a cookie. The producer is expected to wait until the
* consumer is ready to receive another cookie before it
* produces one.
*/
synchronized int waitForCookie() {
cookie = 0;
notify();
while (cookie == 0) {
wait();
}
return cookie;
}
synchronized void setCookie(int c) {
while (cookie != 0) {
wait(); // consumer has not yet consumed the last cookie.
}
cookie = c; // set the cookie and ...
notify(); // tell the consumer that it is available.
}
public void run() {
for (int i = 2; i < 12; i++) {
sleep(50);
setCookie(i);
}
setCookie(100);
}
}
-
Note to Sun employees: this is an EXTERNAL mailing list!
Info: send 'help' to java-interest-request@java.sun.com