Based on Chapter 4 of [Hai19]
(Usage hints for this presentation)
Computer Structures and Operating Systems 2023
Dr. Jens Lechtenbörger (License Information)
lock()
when method is entered
lock()
and
executes a methodunlock()
when method is left
cwait(x)
: Blocks calling thread until csignal(x)
csignal(x)
: Starts at most one thread waiting for x
synchronized
activates locks
this
object during execution of method
E.g., for sample code from [Hai19] (for which you found races previously):
public synchronized void sell() { if (seatsRemaining > 0) { dispenseTicket(); seatsRemaining = seatsRemaining - 1; } else displaySorrySoldOut(); }
synchronized
, this
sell()
from previous slides invoked on some object, say theater
theater
has its own attribute seatsRemaining
seatsRemaining
is really this.seatsRemaining
,
which is the same as theater.seatsRemaining
theater
is unknown, theater
is the this
object, which is used implicitlysynchronized
, races arise when two threads invoke
sell()
on the same object theater
synchronized
, only one of the threads obtains the lock
on theater
, so races are preventedsynchronized
, locks for objects are activated
synchronized
methods, thread needs to acquire lock for this
objectthis
object (e.g.,
seatsRemaining
) are not locked
synchronized
methods)sell()
to use the monitor concept, recompile, and run
again. Observe the expected outcome.(Nothing to submit here; maybe ask questions online.)
synchronized
activates lockpublic synchronized methodAsCS(...) {…}
synchronized (syncObj) {…}
syncObj
wait()
and notify()
, explained
later; ignore for now)synchronized
Examplepublic synchronized void sell() { if (seatsRemaining > 0) { dispenseTicket(); seatsRemaining = seatsRemaining - 1; } else displaySorrySoldOut(); }
synchronized
avoids races
this
object before executing
methodwait()
and hope for notify()
by the latterwait()
and notify()
in Javawait()
: thread unlocks and leaves monitor, enters wait set
notify()
notifyAll()
synchronized
Java Method// Based on Fig. 4.17 of [Hai17] public synchronized void insert(Object o) throws InterruptedException // Called by producer thread { while(numOccupied == buffer.length) // block thread as buffer is full; // cooperation from consumer required to unblock wait(); buffer[(firstOccupied + numOccupied) % buffer.length] = o; numOccupied++; // in case any retrieves are waiting for data, wake/unblock them notifyAll(); }
(Part of SynchronizedBoundedBuffer.java)
synchronized
SynchronizedBoundedBuffer
as shared resourcesynchronized
methods on that bounded buffer
insert()
and retrieve()
wait()
on buffer if unable to continue
this
object used implicitly as target of wait()
notifyAll()
on same buffersynchronized
nor wait/notify
import java.util.concurrent.Semaphore; /* This code is based on Figure 4.18 of the following book: Max Hailperin, Operating Systems and Middleware – Supporting Controlled Interaction, revised edition 1.3, 2017. https://gustavus.edu/mcs/max/os-book/ In Figure 4.18, synchronizedList() is used, whereas here a plain LinkedList is used, which is protected by the additional semaphore mutex. Also, the class here is renamed and implements a new interface. */ public class SemaphoreBoundedBuffer implements BoundedBuffer { private java.util.List<Object> buffer = new java.util.LinkedList<Object>(); private static final int SIZE = 20; // arbitrary private Semaphore mutex = new Semaphore(1); private Semaphore occupiedSem = new Semaphore(0); private Semaphore freeSem = new Semaphore(SIZE); /* invariant: occupiedSem + freeSem = SIZE buffer.size() = occupiedSem buffer contains entries from oldest to youngest */ public void insert(Object o) throws InterruptedException { // Called by producer thread freeSem.acquire(); mutex.acquire(); buffer.add(o); mutex.release(); occupiedSem.release(); } public Object retrieve() throws InterruptedException { // Called by consumer thread occupiedSem.acquire(); mutex.acquire(); Object retrieved = buffer.remove(0); mutex.release(); freeSem.release(); return retrieved; } public int size() { return buffer.size(); } }
java.util.concurrent.Semaphore
acquire()
and release()
SemaphoreBoundedBuffer
implements same interface as
SynchronizedBoundedBuffer
acquire()
and release()
around buffer accesses for MXsynchronized
wait()
and notify()
This document is part of an Open Educational Resource (OER) course on Operating Systems. Source code and source files are available on GitLab under free licenses.
Except where otherwise noted, the work “OS06: MX in Java”, © 2017-2023 Jens Lechtenbörger, is published under the Creative Commons license CC BY-SA 4.0.
In particular, trademark rights are not licensed under this license. Thus, rights concerning third party logos (e.g., on the title slide) and other (trade-) marks (e.g., “Creative Commons” itself) remain with their respective holders.