题目:同步互斥问题
- 生产者消费者问题
- 读者写者问题
1、实验目的
- 利用线程同步机制,实现生产者消费者文体。
- 用信号量机制分别实现读者优先和写者优先的读者-写者问题。
2、实验要求
生产者消费者问题
设计一个程序来解决有限缓冲问题,其中的生产者与消费者进程如图6.10 与图6.11 所示。
在6.6.1 小节中,使用了三个信号量:
- empty (以记录有多少空位)
- full (以记录有多少满位)
- mutex (二进制信号量或互斥信号量,以保护对缓冲插入与删除的操作)。
对于本项目, empty 与full 将采用标准计数信号量,而mutex 将采用二进制信号量。生产者与消费者作为独立线程,在empty、full、mutex 的同步前提下,对缓冲进行插入与删除。
读者写者问题
在Linux环境下,创建一个进程,此进程包含n个线程。
用这n个线程来表示n个读者或写者。每个线程按相应测试数据文件(后面有介绍)的要求进行读写操作。
用信号量机制分别实现读者优先和写者优先的读者-写者问题。
读者-写者问题的读写操作限制(仅读者优先或写者优先):
1)写-写互斥,即不能有两个写者同时进行写操作。
2)读-写互斥,即不能同时有一个线程在读,而另一个线程在写。
3)读-读允许,即可以有一个或多个读者在读。
读者优先的附加限制:如果一个读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。
写者优先的附加限制:如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。
运行结果显示要求:要求在每个线程创建、发出读写操作申请、开始读写操作和结束读写操作时分别显示一行提示信息,以确定所有处理都遵守相应的读写操作限制。
3、实验环境
双系统下的Ubuntu-linux系统
4、实现过程1
- 生产者消费者
设置一个专门存储有限缓冲类型的文件,有限缓冲的数据结构设置为环形数组
struct Buffer{
Buffer(){
count = 0;
front = 0;
rear = 0;
for(int i = 0; i < BUFFER_SIZE; i++){
items[i] = 0;
}
}
buffer_item items[BUFFER_SIZE];
int count;
int front;
int rear;
};
int insert_item(buffer_item item);//生产数据
int remove_item();//消费数据
设置一个专门用于读取文件并按照提议进行处理的结构作为数据结构:
struct data{
int id;
char type;
int start;
int last;
int item;
};
三个信号量:
struct sto{
sem_t mutex;
sem_t nempty;
sem_t nstored;
};
struct sto shared;
生产者线程:
void *produce(void *arg)
{
data *ins = (data*)arg;
sem_wait(&shared.nempty);
sem_wait(&shared.mutex);
sleep(ins->start);
cout << "Producer" << ins->id;
insert_item(ins->item);
sleep(ins->last);
sem_post(&shared.mutex);
sem_post(&shared.nstored);
}
消费者线程:
void *consume(void *arg)
{
data *ins = (data*)arg;
sem_wait(&shared.nstored);
sem_wait(&shared.mutex);
sleep(ins->start);
cout << "Consumer" << ins->id;
remove_item();
sleep(ins->last);
sem_post(&shared.mutex);
sem_post(&shared.nempty);
}
main函数:
int main()
{
FILE *fp;
char file[20];
pthread_t tid_produce;
pthread_t tid_consumer;
data *ins = new data();
sem_init(&shared.mutex, 0, 1);
sem_init(&shared.nempty, 0, 5);
sem_init(&shared.nstored, 0, 0);
fp = fopen("test.txt", "r");
while(fgets(file, 20, fp)){
ins = TodoItem(file);
if(ins->type == 'P'){
cout << "Create Producer No." << ins->id << endl;
pthread_create(&tid_produce, NULL, produce, (void*)ins);
}
else{
pthread_create(&tid_consumer, NULL, consume, (void*)ins);
cout << "Create Consumer No." << ins->id << endl;
}
}
sem_destroy(&shared.mutex);
sem_destroy(&shared.nempty);
sem_destroy(&shared.nstored);
sleep(60);
return 0;
}
运行结果
5、实现过程2
- 读者写者问题之读者优先问题
设置一个专门用于读取文件并按照提议进行处理的结构作为数据结构:
struct data{
int id;
char type;
int start;
int last;
int item;
};
两个信号量:
struct sto{
sem_t mutex;
sem_t write;
};
struct sto shared;
用一个整型变量count记录当前的读者数目,用于确定是否需要释放正在等待的写者线程。
int count;
读者线程:
void *toRead(void *arg)
{
data *ins = (data*)arg;
sleep(ins->start);
cout << "Reader " << ins->id << " requests to read." << endl;
sem_wait(&shared.mutex);
count++;
if(count == 1) sem_wait(&shared.write);
sem_post(&shared.mutex);
//开始读取共享数据段
cout<<"Reader "<<ins->id<<" is reading."<<endl;
sleep(ins->last);
cout<<"Reader "<<ins->id<<" end reading."<<endl;
//读取完毕后,读者数目减去1。
//只有全部读者读取完毕后,唤醒写者线程
sem_wait(&shared.mutex);
count--;
if(count == 0) sem_post(&shared.write);
sem_post(&shared.mutex);
}
写者者线程:
void *toWrite(void *arg)
{
data *ins = (data*)arg;
sleep(ins->start);
cout << "Writer " << ins->id << " requests to write." << endl;
sem_wait(&shared.write);
cout<<"Writer "<<ins->id<<" is writing."<<endl;
sleep(ins->last);
cout<<"Writer "<<ins->id<<" end writing."<<endl;
sem_post(&shared.write);
}
main函数:
int main()
{
FILE *fp;
char file[20];
pthread_t tid_produce;
pthread_t tid_consumer;
data *ins = new data();
sem_init(&shared.mutex, 0, 1);
sem_init(&shared.nempty, 0, 5);
sem_init(&shared.nstored, 0, 0);
fp = fopen("test.txt", "r");
while(fgets(file, 20, fp)){
ins = TodoItem(file);
if(ins->type == 'P'){
cout << "Create Producer No." << ins->id << endl;
pthread_create(&tid_produce, NULL, produce, (void*)ins);
}
else{
pthread_create(&tid_consumer, NULL, consume, (void*)ins);
cout << "Create Consumer No." << ins->id << endl;
}
}
sem_destroy(&shared.mutex);
sem_destroy(&shared.nempty);
sem_destroy(&shared.nstored);
sleep(60);
return 0;
}
运行结果
5、实现过程3
- 读者写者问题之写者优先问题
设置一个专门用于读取文件并按照提议进行处理的结构作为数据结构:
struct data{
int id;
char type;
int start;
int last;
int item;
};
五个信号量:
struct sto{
sem_t mutex;//保证每次只有一个读者进入临界区
sem_t mutex1;//保证read操作原子性
sem_t mutex2;//保证write操作原子性
sem_t read;//读者是否可读
sem_t write;//写着是否可读取数据段
};
struct sto shared;
用于记录正在等待的写者的数目w_count和用于记录正在等待的读者的数目r_count。
int r_count;
int w_count;
读者线程:
void *toRead(void *arg)
{
data *ins = (data*)arg;
sleep(ins->start);
cout << "Reader "<<ins->id<<" requres to read" << endl;
sem_wait(&shared.mutex);
sem_wait(&shared.read);
sem_wait(&shared.mutex1);
r_count++;
if(r_count == 1)
sem_wait(&shared.write);
sem_post(&shared.mutex1);
sem_post(&shared.read);
sem_post(&shared.mutex);
cout<<"Reader "<<ins->id<<" starts to read."<<endl;
sleep(ins->last);
cout<<"Reader "<<ins->id<<" end reading."<<endl;
sem_wait(&shared.mutex1);
r_count--;
if(r_count == 0)
sem_post(&shared.write);
sem_post(&shared.mutex1);
}
写者者线程:
void *toWrite(void *arg)
{
data *ins = (data*)arg;
sleep(ins->start);
cout << "Writer "<<ins->id<<" requres to write" << endl;
sem_wait(&shared.mutex2);
w_count++;
if(w_count == 1)
sem_wait(&shared.read);
sem_post(&shared.mutex2);
sem_wait(&shared.write);
cout<<"Writer "<<ins->id<<" starts to write."<<endl;
sleep(ins->last);
cout<<"Writer "<<ins->id<<" end writing."<<endl;
sem_post(&shared.write);
sem_wait(&shared.mutex2);
w_count--;
if(w_count == 0)
sem_post(&shared.read);
sem_post(&shared.mutex2);
}
main函数:
int main()
{
FILE *fp;
char file[20];
pthread_t tid_read;
pthread_t tid_write;
data *ins = new data();
sem_init(&shared.mutex, 0, 1);
sem_init(&shared.mutex1, 0, 1);
sem_init(&shared.mutex2, 0, 1);
sem_init(&shared.write, 0, 1);
sem_init(&shared.read, 0, 1);
fp = fopen("test.txt", "r");
while(fgets(file, 20, fp)){
ins = TodoItem(file);
if(ins->type == 'R'){
cout << "Create a reader pthread-No." << ins->id << " pthread." << endl;
pthread_create(&tid_read, NULL, toRead, (void*)ins);
}
else{
pthread_create(&tid_write, NULL, toWrite, (void*)ins);
cout << "Create a writer pthread-No." << ins->id << " pthread." << endl;
}
}
sem_destroy(&shared.mutex);
sem_destroy(&shared.mutex1);
sem_destroy(&shared.mutex2);
sem_destroy(&shared.read);
sem_destroy(&shared.write);
//sem_destroy(&shared.nstored);
sleep(60);
return 0;
}
运行结果