Laboratory 3:
Synchronization Using Semaphores
一:Objectives(实验目标)
In this laboratory session, you are required to write a test program for the producer/consumer
problem using semaphores for synchronization. After completing the session, you will
_ have a understanding in Nachos of
– how semaphores are implemented, and
– how the producer/consumer problem is implemented using semaphores
_ know how to create concurrent threads in Nachos, and
_ know how to test and debug programs in Nachos.
The work of this laboratory session will prepare you for the programming task in Assignment 2.
二:实验环境
In this laboratory session, you are required to implement the producer/consumer algorithm in Nachos
using semaphores for synchronization.
In your ../lab3/ directory, you can find files: main.cc, prodcons++.cc, ring.cc and ring.h.
Files ring.cc and ring.h define and implement a class Ring for the ring buffer used by producers
and consumers. These two files are complete and you do not need to change any part of them.
main.cc in this directory is modified from the version in ../threads/. It is complete and you do
not need to change it.
In the new main.cc, function ProdCons() is called instead of ThreadTest(). Function ProdCons()
is defined in file prodcons++.cc. This file is supposed to include the code to create producer and
consumer threads as well as implement the producer/consumer algorithm described in the textbook.
However, this file is not complete yet. Your task in this laboratory session is to complete this file
and make the producer/consumer algorithm work.
File prodcons++.cc contains all the data structures and the interfaces of the functions. There are
detailed comments in the file about what needs to be done in each part of the code. Because all
the interfaces of the functions are present, the file is compilable. You can execute make in the
../lab3/ now to make a new Nachos for producer/consumer problem. (But it won’t work yet
because prodcons++.cc is incomplete.)
三:关键代码注释:
Producer:
nfull->P(); //等待其非full
mutex->P(); //等待获得锁(等待信号量大于0)
ring->Put(message);
// Put the code for synchronization after ring->Put(message) here.
mutex->V(); //释放锁(信号量+1)
nempty->V(); //发出一个非empty信号
consumer:
for (; ; ) {
// Put the code for synchronization before ring->Get(message) here.
nempty->P(); //等待其非empty
mutex->P(); //等待获得锁
ring->Get(message);
// Put the code for synchronization after ring->Get(message) here.
mutex->V(); //释放锁
nfull->V(); //发出一个非full信号
ProCons:
ProdCons()
{
int i;
DEBUG('t', "Entering ProdCons");
// Put the code to construct all the semaphores here.
mutex = new Semaphore("Entering ProdCons", 1);
nfull = new Semaphore("Entering ProdCons", BUFF_SIZE);
nempty = new Semaphore("Entering ProdCons", 0);
// Put the code to construct a ring buffer object with size
//BUFF_SIZE here.
ring = new Ring(BUFF_SIZE);
// create and fork N_PROD of producer threads
for (i=0; i < N_PROD; i++)
{
// this statemet is to form a string to be used as the name for
// produder i.
sprintf(prod_names[i], "producer_%d", i);
// Put the code to create and fork a new producer thread using
// the name in prod_names[i] and
// integer i as the argument of function "Producer"
producers[i] = new Thread(prod_names[i]);
producers[i]->Fork(Producer, i);
};
// create and fork N_CONS of consumer threads
for (i=0; i < N_CONS; i++)
{
// this statemet is to form a string to be used as the name for
// consumer i.
sprintf(cons_names[i], "consumer_%d", i);
// Put the code to create and fork a new consumer thread using
// the name in cons_names[i] and
// integer i as the argument of function "Consumer"
consumers[i] = new Thread(cons_names[i]);
consumers[i]->Fork(Consumer, i);
};
四:调试记录:
运行./nachos
消费者写入的第一个文件
消费者写入的二个文件:
五:运行结果分析:
设置了三个缓冲区,在其中先创建两个生产者,在缓冲区中生产,直到缓冲区为满时,停止生产,同时创建两个消费者在缓冲区内无限消费,直到缓冲区空时,停止消费,并将实验结果写入文件中,运行结果会出现消费者在文件中多次运行消费固定数额的产品,如果在运行时加入-rs 时间片的话,消费者消费的数额才会变,那是操作系统的默认函数切换时间片到另一个消费者,因此出现的结果会发生变化。可以改变缓冲区的数量,结果没变,因为缓冲区不影响生产者和消费者的过程。也可以改变消费者和生产者的数量,生产者改变,那生产的产品数就等于生产者数乘以4(默认一个生产者生产四个),消费者改变,那么产生的文件数也会改变。