-
Name the only three distinct, primitive solutions to the critical
section problem presented in class, where primitive means `does not rely
on some other primitive solution.'
- What is a semaphore?
- What is a spinlock?
- (true / false) Starvation is not possible with a fair semaphore.
-
The Sleeping-Barber Problem:
A barbershop consists of a waiting room and n chairs and a barber room with
one barber chair. If there are no customers to be serviced, the barber goes to
sleep. If a customer enters the barbershop and all chairs are occupied, then
the customer leaves the shop. If the barber is busy but chairs are available,
then the customer sits in one of the free chairs. If the barber is asleep, the
customer wakes up the barber.
Write a complete Java program using a monitor to coordinate the barber
and the customers. Specifically, using only the Customer and
Factory classes below, complete the definition of the BarberShopMonitor
class by providing a definition for the customerEnters(int id) method. Do
not modify these classes at all. You must only complete the data member section
and provide definitions for the constructor and the customerEnters(int
id) method. Moreover, for full credit, your solution must be fair,
(i.e., no new customer should be able to cut ahead of a customer in the waiting
room). If you recall, the semaphore solution presented in class suffered from
this problem.
public class Factory {
public static final int NUM_OF_CHAIRS = 10;
public static final int NUM_OF_CUSTOMERS = 100;
public static void main(String args[]) {
BarberShopMonitor bsmonitor = new BarberShopMonitor(NUM_OF_CHAIRS);
for (int i = 0; i < NUM_OF_CUSTOMERS; i++) {
(new Thread(new Customer(i, bsmonitor))).start();
if ((i % 3) == 0) SleepUtilities.nap();
}
}
}
class Customer implements Runnable {
int id;
BarberShopMonitor bsmonitor;
Customer (int id, BarberShopMonitor bsmonitor) {
this.id = id;
this.bsmonitor = bsmonitor;
}
public void run() {
bsmonitor.customerEnters(id);
}
}
class BarberShopMonitor {
BarberShopMonitor(int num_chairs) {
}
void customerEnters(int id) {
}
private void service(int id) {
System.out.println ("Customer " + id + " is being serviced.");
SleepUtilities.nap();
System.out.println ("Customer " + id + " is done being serviced.");
}
-
Solve the following three problems in the Sleeping Barber problem.
problem 1: Assume the barber is in use and there is only one chair left in
the waiting room. Further, assume that a new customer slices after trying to
acquire the barber, but before trying to acquire a chair in the waiting room.
Under these circumstances, a new customer can occupy the last
available chair in the waiting room, effectively cutting the line.
problem 2: Assume the barber is available, but the waiting room is full. In
this scenario, a new customer can cut the entire line.
problem 3: Assume the barber is available and the waiting room is full. Further,
assume that a customer in the waiting room slices after acquiring the barber,
but before release their chair in the waiting room. Under these circumstances, a
new customer will leave the shop because their are no seats available in the
waiting room, even though there really is one available.
Can all three of these problems be solved concomitantly in a semaphore solution
to the Sleeping Barber problem, or is a monitor necessary? In more general
terms, are semaphores and monitors as powerful as each other, or are there some
problems for which a semaphore solution does not exist, though a monitor
solution does exist?
- What is a monitor?
-
When a monitor uses signal and exit semantics, as opposed to signal and continue
semantics, where do the signaling threads/processes go?
-
Explain why you must only use the Java wait() method within the
body of a while loop, and never within the body of an if statement.
-
Suppose, a file is to be shared among several different processes.
The file can be accessed concurrently by several processes as long as the sum
of all pids associated with all of the processes currently accessing the file
is less than n.
Define a monitor using the Hoare monitor model which
coordinates access to the file given this constraint. You may assume that no
pid is greater than n.
-
Consider only three thread types (A, B, and C) with the following constraints:
- mutual exclusion among the Cs,
- maximum 5 Bs in at one time,
- mutual exclusion between the As and Bs,
- mutual exclusion between the As and Cs, and
- when a type X thread leaves the monitor, if a non-X
thread type and a type X thread both want and are safe
to enter the monitor, the non-X thread type has priority.
Complete the definition of the Java monitor Monitor class below
to solve this problem. Do not add any new methods to the Monitor class,
or any new classes. Only complete the data member section and provide
definitions for the constructor and the 6 entry and exit methods.
import java.util.concurrent.*;
import java.util.concurrent.locks.*;
class Monitor {
ReentrantLock lock;
Monitor() {
lock = new ReentrantLock();
}
public void Aentry() {
lock.lock();
lock.unlock();
}
public void Aexit() {
lock.lock();
lock.unlock();
}
public void Bentry() {
lock.lock();
lock.unlock();
}
public void Bexit() {
lock.lock();
lock.unlock();
}
public void Centry() {
lock.lock();
lock.unlock();
}
public void Cexit() {
lock.lock();
lock.unlock();
}
}
-
Consider only three thread types (A, B, and C) with the following constraints:
- mutual exclusion among the As,
- mutual exclusion between the Bs and Cs,
- mutual exclusion between the As and Cs, and
- priority to the As (i.e., additional Cs must not enter the if one or
more As are waiting to enter the , and if an opportunity arises to
signal an A or C, signal the A.)
Implement a Java monitor without condition variables to coordinate the activity
of these threads (i.e., use the implicit monitor available in any Java object,
rather than building a monitor from first principles. This also means you are
unable to use Java condition variables).
-
A group of fraternity brothers and sorority sisters is having a party and
drinking from a large communal keg which can hold servings of root beer. One
unlucky pledge is not allowed to participate in the party and rather must sleep
in the tool shed. This particular pledge also has the unfortunate responsible
of replacing the keg each time it empties. When a guest wants to drink, he or
she fills a cup from the keg, unless the keg is empty. If the keg is empty,
the guest goes to the tool shed, obnoxiously wakes up the pledge, returns to
the party, and then waits to drink until the pledge has returned with a new
keg. The guest who wakes up the pledge need not be the guest to drink the first
cup from the new filled keg. In other words, your solution need not prevent
starvation. The behavior of the guests and the unlucky pledge is specified by
the following Java classes:
class Guest implements Runnable {
House house;
Guest (House house) {
this.house = house;
}
public void run {
house.tellPledgeIfKegEmpty();
house.getServingFromKeg();
// drink
}
}
class Pledge implements Runnable {
House house;
Pledge (House house) {
this.house = house;
}
public void run {
while (house.getNumGuests() > 0) {
house.waitForKegToEmpty();
house.getNewKegOfNservings();
}
}
}
class Party {
private static final int CAPACITY_OF_KEG = 24;
private static final int NUM_GUESTS = 100;
public static void main(String args[]) {
House house = new House(CAPACITY_OF_KEG, NUM_GUESTS);
(new Thread (new Pledge(house))).start();
for (int i=0; i < NUM_GUESTS; i++)
(new Thread (new Guest(i, house))).start();
}
}
Develop a complete Java semaphore solution to this problem. Specifically,
complete the definition of the House class below. Do not add any new methods
to the House class, or any new classes. Only complete the data member section
and the definition of the constructor, and provide definitions for the four
methods. Your solution must avoid deadlock and only awaken the pledge when the
keg is empty. You must not use a monitor to solve this problem.
Hint: in addition to the standard acquire and release semaphore operations,
you may also assume availablePermits (which returns the semaphore value) and
release(int n) (which adds n to the semaphore value) operations.
class House {
int capacity_of_keg;
int num_guests;
House (int capacity_of_keg, int num_guests) {
// keg starts full
this.capacity_of_keg = capacity_of_keg;
this.num_guests = num_guests;
}
void tellPledgeIfKegEmpty() {
}
void getServingFromKeg() {
}
void waitForKegToEmpty() {
}
void getNewKegOfNservings() {
}
public int getNumGuests() {
return num_guests;
}
}
-
Solve the Party problem above using the classical
Hoare monitor model.
The pledge process and the guest processes are described as follows:
process Guest {
while (true) {
guest_entrance();
//
guest_exit();
}
}
process Pledge {
while (true) {
pledge_entrance();
//
pledge_exit();
}
}
Provide a complete definition of the monitor (i.e., provide the
declarations/definitions of the shared data as well as the definition of the
entrance and exit procedures).
-
Solve the Party problem above using the Java monitor model. The behavior of
the guests and the unlucky pledge is specified by the Java classes below.
Provide the definition of the Java monitor House class below to solve this
problem. Only provide the definitions of the guestentrance, guestexit,
pledgeentrance, and pledgeexit methods. Assume the exact same Party class as
given in problem 2. Since the Java monitor model does not follow
Hoare's model
completely (or at all), you need not translate your solution to the problem 2
directly into Java (i.e., it is okay to take a different solution approach).
-
In software engineering, a design pattern is
a general reusable solution to a re-occurring problem in software design.
There are catalogs of design patterns. One such pattern is called the
Singleton pattern. It ensure that only one instance of an object is created.
For instance, if we have a class called BestFriend, we wish to allow only
one instance of it. Thus, rather than creating a BestFriend object using
its constructor, we instead declare the constructor as private and
provide a public static method getInstance() for object creation.
Recall a static method is one which need not be called through a
particular instance of an object. Rather it is called through the class itself
akin to a function in C (which also is not associated with an object). For
instance,
BestFriend mary = BestFriend.getInstance();
The following is one strategy for implementing the Singleton
pattern. The idea behind this approach is to use lazy
initialization, whereby we create an instance of the object
only when it is needed (i.e., when getInstance()) is
first called.
public class BestFriend {
private static BestFriend instance = null;
private BestFriend() { }
public static BestFriend getInstance() {
if (instance == null)
instance = new BestFriend();
return instance;
}
}
Does this implementation of the Singleton
pattern involve a race condition?
If so, identify it (be clear and specific) and
modify the implementation above in place
to eliminate the race condition. If not, state why not.
-
Suppose a file is to be shared among several different processes.
The file can be accessed concurrently by several processes as
long as the sum of all pids associated with all of the processes
currently accessing the file is less than n. Define a monitor
using the Hoare monitor model which coordinates access to the
file given this constraint. You may assume that no pid is greater than
n.