CS202: HW 4: More concurrency

CS202: HW 4: More concurrency

These problems should be done on your own. We're not going to be grading them strictly (we'll mainly look at whether you attempted them). But they will be reinforcing knowledge and skills, so you should totally work through them carefully.

Synchronization: warmup

This problem is based on the following code (which is similar to Problem 5 of Homework 3):

    int i = 0; 

    /* ADD SOME THINGS HERE */

    void
    foo(void *)
    {
        printf("I am foo!!!\n");
        
        /* ADD SOME CODE HERE */
    }

    void
    boo(void *)
    {
        /* ADD SOME CODE HERE */

        printf("I am boo!!!\n");
    }

    int
    main(int argc, char** argv)
    {
        create_thread(foo);
        create_thread(boo);

        // wait for threads to finish
        // before exiting
        join_thread(foo);
        join_thread(boo);

        exit(0);
    }

Modify the code above to ensure that I am foo!!! prints before I am boo!!!. Use mutexes and condition variables.

More practice with synchronization

Consider a system with three smoker processes and one agent process. Each smoker continuously rolls a cigarette and then smokes it. But to roll and smoke a cigarette, the smoker needs three ingredients: tobacco, paper, and matches. One of the smoker processes has paper, another has tobacco, and the third has matches. The agent has an infinite supply of all three materials.

The agent places two of the ingredients on the table. The smoker who has the remaining ingredient then makes and smokes a cigarette, signaling the agent on completion. The agent then puts out another two of the three ingredients, and the cycle repeats.

Assume the agent calls the procedure

void chooseIngredients(int *paper, int *tobacco, int *match);

to randomly select 2 of the 3 ingredients. The routine randomly sets 2 of the ints to "1" and one of them to "0". You don't have to write this routine.

Write a program to synchronize the agent and smokers:

  1. What synchronization and state variables will you use in this problem? (For each variable, indicate the variable's type, the variable's name, its initial value (if any), and a short comment describing the variable's purpose.)

    Variable Name        Variable Type        Initial Value        Description

  2. Write the routines Agent() and matchSmoker() (the routine for the smoker that has lots of matches). You don't have to write the routines paperSmoker() or tobaccoSmoker(), but your solution should be general enough so that those routines would be simple variations of matchSmoker().

Sleeping barber

This is a potentially useful (if convoluted) example to exercise your understanding of how to use mutexes and conditional variables. It is a well-known concurrency problem. The writeup and solution are due to Mike Dahlin (who used to be on the faculty at The University of Texas at Austin). He asked this question on a midterm in 2002.

Work through the problem on your own; we will post the solution next week.

A shop has a barber, a barber chair, and a waiting room with NCHAIRS chairs. If there are no customers present, the barber sits in the chair and falls asleep. When a customer arrives, the customer wakes the sleeping barber. If an additional customer arrives while the barber is cutting hair, the customer sits in a waiting room chair if one is available. If no chairs are available, the customer leaves the shop. When the barber finishes cutting a customer’s hair, the barber tells the customer to leave; then, if there are any customers in the waiting room, the barber announces that the next customer can sit down. Customers in the waiting room get their hair cut in FIFO order.

The barber shop can be modeled as 2 shared objects:

Thus, each customer thread executes the code:

Customer(WaitingRoom *wr, BarberChair *bc)
{
    status = wr->enter();
    if (status == WR_FULL) {
        return;
    }
    bc->wakeBarber();
    bc->sitInChair();   // Wait for chair to be EMPTY
                        // Make state LONG_HAIR_CUSTOMER_IN_CHAIR
                        // Wait until SHORT_HAIR_CUSTOMER_IN_CHAIR
                        // then make chair EMPTY and return
    return;
}

The barber thread executes the code:

Barber(WaitingRoom *wr, BarberChair *bc)
{
    while (1) { // A barber’s work is never done
        status = wr->callNextCustomer();
        if (status == WR_EMPTY) {
            bc->napInChair(); // Set state to BARBER_IN_CHAIR; return with state EMPTY
        }
        bc->cutHair(); // Block until LONG_HAIR_CUSTOMER_IN_CHAIR;
                       // Return with SHORT_HAIR_CUSTOMER_IN_CHAIR
        bc->tellCustomerDone(); // Return when EMPTY
    }
}

Write the code for the WaitingRoom class and the BarberChair class. Use locks and condition variables for synchronization. Follow the coding standards specified in Mike Dahlin’s Coding Standards for Threads Programming, which you will also follow in Lab 3.

Hints (and requirement reminders):

  • remember to start by asking for each method “when can a thread wait?” and writing down a synchronization variable for each such situation.

  • List the member variables of class WaitingRoom including their type, their name, and their initial value. Then write the methods for WaitingRoom.

  • List the member variables of class BarberChair including their type, their name, and their initial value. Then write the methods for BarberChair.

Handing in the homework

Use Gradescope; you can enroll in our course with entry code JBGJKG. (And please feel free to send us feedback about Gradescope.)