linux使用多线程解决“读者—写者”问题实验报告

合集下载

读者写者问题实验报告

读者写者问题实验报告

读者写者问题实验报告1. 引言读者写者问题是操作系统中的经典同步问题,用于研究多线程环境下对共享资源的访问和保护。

在该问题中,有多个读者和写者同时对一个共享资源进行操作,需要保证并发访问时的正确性和效率。

通过本实验,我们将探讨读者写者问题的解决方案,并比较不同算法的性能差异。

2. 实验目标本实验的主要目标是通过实现和比较不同的读者写者问题算法,深入了解并发访问的挑战和解决方案。

具体而言,我们将研究以下几个方面:•设计并实现读者写者问题的解决方案•比较不同算法的性能差异•分析可能的优化策略3. 实验方法我们将使用Python编程语言来实现读者写者问题的解决方案。

在实验过程中,我们将尝试以下几种常见的算法:3.1. 读者优先算法在读者优先算法中,当有读者在访问共享资源时,其他读者可以同时访问,但写者需要等待。

只有当所有读者完成访问后,写者才能获得访问权限。

3.2. 写者优先算法在写者优先算法中,当有写者在访问共享资源时,其他读者和写者都需要等待。

只有当写者完成访问后,其他读者或写者才能获得访问权限。

3.3. 公平算法在公平算法中,读者和写者的访问权限是公平的,先到先得。

无论读者还是写者,都需要按照到达的顺序依次获取访问权限。

4. 实验步骤下面是我们实施实验的具体步骤:4.1. 实现基本的读者写者问题解决方案我们首先实现基本的读者写者问题解决方案,包括读者和写者的线程逻辑和共享资源的访问控制。

我们将使用互斥锁和条件变量来保证并发访问的正确性。

4.2. 实现读者优先算法在已有的基本解决方案的基础上,我们实现读者优先算法。

我们将通过优化访问控制的逻辑来实现读者优先的特性。

4.3. 实现写者优先算法类似地,我们在基本解决方案的基础上实现写者优先算法。

我们将调整访问控制的逻辑,使得写者优先于其他读者和写者。

4.4. 实现公平算法最后,我们实现公平算法。

我们将结合队列和条件变量等技术来确保读者和写者的访问顺序是公平的。

OS:读者写者问题(写者优先+LINUX+多线程+互斥量+代码)

OS:读者写者问题(写者优先+LINUX+多线程+互斥量+代码)

OS:读者写者问题(写者优先+LINUX+多线程+互斥量+代码)⼀. 引⼦最近想⾃⼰写个简单的 WEB SERVER ,为了先练练⼿,熟悉下在LINUX系统使⽤基本的进程、线程、互斥等,就拿以前学过的 OS 问题开开⼑啦。

记得当年学读者写者问题,尤其是写者优先的时候,那是真⼼纠结啊。

刚才还觉得理解了,过⼀会⼉⼜糊涂了。

现在重新再看,还是容易纠结。

没办法,⽤得少。

我把读者优先和写者优先都实现了⼀下。

选择性重看了⼩部分《unix⾼程》使⽤了多线程+互斥量实现。

⼆. 互斥量与信号量互斥量如其名,同⼀时间只能被⼀个线程占有,实现线程间对某种数据结构的互斥访问。

试图对⼀个已经加锁的互斥量加锁,会导致线程阻塞。

允许多个线程对同⼀个互斥量加锁。

当对互斥量解锁时,阻塞在该互斥量上的线程会被唤醒,它们竞争对该互斥量加锁,加锁成功的线程将停⽌阻塞,剩余的加锁失败于是继续阻塞。

注意到,谁将竞争成功是⽆法预料的,这⼀点就类似于弱信号量。

(强信号量把阻塞在信号量上的进程按时间排队,先进先出)互斥量区别于信号量的地⽅在于,互斥量只有两种状态,锁定和⾮锁定。

它不像信号量那样可以赋值,甚⾄可以是负值。

共性⽅⾯,我所体会到的就⼀句话,都是⽤来实现互斥的。

⾄于其它区别或联系,⽤不上,不作研究。

三. 读者优先只要有⼀个读者正在读,那么后续的读者都能⽴即读,不管有多少写者在等待。

可能导致写者饥饿。

1. 读者1) 写者写时,不可读2) 有别的读者正在读,可读2. 写者1) 有读者正在读,不可写2) 有写者正在写,不可写3) ⽆读者正在读,⽆写者正在写,可写四. 写者优先当新的写者希望写时,不允许该写者后续的读者访问数据区,但必须保证之前的读者读完。

1. 读者特点1) 有写者正在写或者等待写,须等到没有写者才能读2) 没有写者,可以读2. 写者特点1) 写者与写者互斥。

当其它写者正在写时,其它写者不能写。

2) 写者与读者互斥。

之前只有读者在读,当写者出现时,必须等到之前的读者都读完才能写。

读者写者问题实验报告

读者写者问题实验报告

北京电子科技学院(BESTI)实验报告课程:操作系统班级:0921 姓名:学号:成绩:指导教师:徐小青实验日期:2011.11.22 实验密级:/ 预习程度:代码实验时间:12:50-15:20 仪器组次:A04 必修/选修:必修实验序号:(一)实验名称:用信号量来实现读者-写者问题实验目的与要求:理解进程(或线程)及信号量的概念实验仪器:一、实验目的:理解进程(或线程)及信号量的概念二、实验内容:1、定义一个数据缓存buffer及用于实现同步互斥的信号量。

2、定义一个读者函数:●当有写者在占用buffer时,读者应该等待,直到写者不再使用该buffer。

●当有其他读者在占用buffer时,读者可对buffer进行读取操作。

●当buffer中有数据时,则从其中读取一个数据,并显示然后退出。

●当buffer中没有数据时,应等待,直到buffer中有数据可读。

3、定义一个写者函数●当有读者在占用buffer时,写者应该等待,直到所有的读者都退出为止。

●当有其他写者占用buffer时,该写者应该等待,直到占用buffer的写者退出为止。

●当buffer有空闲时,写者应该在buffer中写入一个数据并退出。

●当buffer满时,写者应该等待,直到buffer有空闲为止。

4、定义主函数,在其中可以任意创建读者与写者。

可根据用户输入创建读者或写者进程(线程)。

三、实验当堂完成内容:1,将设计好的思路以代码形式呈现,并调通。

2,将数据改变,看结果是否符合预期设想3,与同学交流,将代码完善。

四、设计思想:读进程:read(){P(Sr); 申请区域P(Scot); 锁定读者计数器first = first+1;if(first ==1)P(Sdoc);V(Scnt); 解锁读者计数器开始读;P(Scnt); 锁定读者计数器V(Sdoc);V(Scnt);V(Sr);}写进程:write(){P(sdoc);开始写;V(sdoc);}主函数设计思想:五、代码及具体解释:#include <stdlib.h>#include <windows.h>#include <stdio.h>#define P(S) WaitForSingleObject(S, INFINITE)// 这是Windows 下多线程工作的P 操作#define V(S) ReleaseSemaphore(S, 1, NULL)// 这是Windows 下多线程工作的V 操作const int RN = 5 ; // 所有读者总数(可以改变)const int WN = 3; // 所有写者总数(可以改变)HANDLE Sdoc; // 文档信号量——互斥量(临界区的信号量题目要求是1)HANDLE Sr; // 读者信号量——广义信号量(一次最多有多少个读者在读)HANDLE Scnt; // 保护g_cntReader 的互斥量(目前有多少读者正在读)int g_cntReader = 0; // 读者个数计数器// funcname : JustWait ( )// note: 显示一些信息,让后等待// ret val : void//// + Parameter :// [ int ] - nReader 读者(写者)编号,读者>0,写者<0// [ int ] - min 操作等待的最短时间// [ int ] - max 操作等待得最长时间,实际等待的时间介于两者之间// [ LPCSTR ] - info 要显示的信息void JustWait(int nReader, int min, int max, LPCSTR info);DWORD WINAPI Reader(LPVOID lpPara);DWORD WINAPI Writer(LPVOID lpPara);// 这是主函数void main(){Sdoc = CreateSemaphore(NULL, 1, 1, "Document");// 创建信号量初值,最大信号量值Sr = CreateSemaphore(NULL, 3, 3, "ReaderNumber"); // 一次最多允许3 个Scnt = CreateSemaphore(NULL, 1, 1, "ReaderCounterProtect");// 他也是一个互斥信号量,初值为 1HANDLE threads[RN+WN];for (int i=0; i<RN; i++) //不断创建读者线程threads[i] = CreateThread(0, 0, Reader, 0, 0, 0);for (int j=0; j<WN; j++)threads[j+RN] = CreateThread(0, 0, Writer, 0, 0, 0);WaitForMultipleObjects(RN+WN, threads, TRUE, INFINITE);}// 读者线程DWORD WINAPI Reader(LPVOID lpPara){// 注意是静态变量,可以使每来一个读者增加一static int reader_num = 1;int i = reader_num ++;int x=0;while (x<=5){JustWait(i, 1, 2, "我想读"); //1s的时候来,给2s的时间去读P(Sr); // 读者未满P(Scnt); // 锁定读者计数器printf("还有%d 个读者在读, 读者%d进入\n", g_cntReader, i);g_cntReader ++;if (g_cntReader == 1) // 如果是第一个读者{JustWait(i, 1, 2, "我是第一个!");P(Sdoc); // 锁定文档printf("读者%d说:有人在读,不可写文件\n", i);JustWait(i, 1, 2, "我可以读文件了!");V(Scnt); // 解锁读者计数器释放JustWait(i, 2, 5, "我在读");// 读ing…………JustWait(i, 1, 2, "我将要离开!");P(Scnt); // 锁定读者计数器g_cntReader --;if (g_cntReader == 0) // 如果是最后一个{JustWait(i, 1, 2, "我是最后一个!");printf("读者%d说:可以对文件操作了!~~~\n", i);V(Sdoc);// 解锁文档}printf("还有%d个读者在, 读者%d离开\n", g_cntReader, i);V(Scnt);// 解锁读者计数器V(Sr); // 离开JustWait(i, 5, 3, "结束");x++;printf("%d\n",x);}return 0;}DWORD WINAPI Writer(LPVOID lpPara){// 注意是静态变量,可以使每来一个写者减去一,注意初值是负值static int g_cnt = -1;int j = g_cnt --;while (1){JustWait(j, 2, 4, "我想写");// 锁定文档P(Sdoc);printf("\t写者%d说:文件正在修改不可操作\n", -j);JustWait(j, 4, 3, "写···"); // 写ing……JustWait(j, 1, 2, "写完了,离开");printf("写者%d说:可以对文件操作了\n", -j);V(Sdoc);// 解锁文档JustWait(j, 8, 4, "休息了");}return 0;}void JustWait(int nReader, int min, int max, LPCSTR info)//min为读者到来时间,max为读者离开时间{const int BASETIME = 1000;// 等待时间的基本量,以毫秒表示int wait_time = 0;// 实际等待得时间if (max==min) // 判断是为了避免%0错误,注意取随机值wait_time = min*BASETIME;//处理时间为0;elsechar s_out[128];// 最终显示的信息缓冲if (nReader > 0)// 读者大于0,写者小于0sprintf(s_out, "读者%d说: %s\n", nReader, info);elsesprintf(s_out, "\t写者%d说: %s\n", -nReader, info);printf(s_out);// 打印Sleep(wait_time);// 然后等待}//其设计思想是:读者在读,来了写着,创建写着线程,利用时间片区分他们。

读写者实验报告

读写者实验报告

《Linux系统分析》实验报告报告提交日期:姓名:程志超学号: 128355003 班级:交换生一、实验题目采用多线程互斥与同步机制,实现读者、写者问题二、实验目的掌握使用POSIX接口提供的互斥变量、条件变量实现多线程同步三、实验要求有一个文件为多个并发线程所共享,其中读线程只要求读取文件内容,写线程则要求修改文件容,允许多个线程同时读取文件内容。

但若有一个写线程在写,则其他读线程不能读;若有一个写线程在写或有其他读线程在读,则其他写线程均被拒绝。

当一个写线程正在写,而有多个读线程与写线程在等待时,写线程应优先唤醒。

读线程进去读、等待,写线程进去写、等待等状态均在屏幕上打印出来四、设计思路和流程图(对于涉及算法的实验,需要提供数据结构及其说明、测试数据的设计及测试结果分析)数据结构的说明struct prodcons{int buffer[BUFFERSIZE]; //缓冲区pthread_mutex_t lock; //互斥锁int readpos,writepos; //读写的游标pthread_cond_t notempty; //缓冲区非空条件判断pthread_cond_t notfull; //缓冲区非满条件判断};测试结果:读和写的线程交互进行五、实验体会(包括实验中遇到的问题及解决过程、产生的错误及原因分析)对线程条件变量控制相关函数pthread_cond_init()、pthread_cond_wait()和pthread_cond_signal()的原型及用法不是很了解,上网查阅相关资料,明白第一个是初始化一个条件变量,第二个等待线程,尤其要注意线程状态和条件变量的加解锁过程是/*block-->unlock-->wait() return-->lock*/六、程序清单(包括源程序、makefile、readme)/***multithread.c***/#include<stdio.h>#include<pthread.h>#define BUFFERSIZE 100#define OVER (-1)struct prodcons{int buffer[BUFFERSIZE];pthread_mutex_t lock;int readpos,writepos;pthread_cond_t notempty;pthread_cond_t notfull;};void init(struct prodcons *b){pthread_mutex_init(&b->lock,NULL);pthread_cond_init(&b->notempty,NULL);pthread_cond_init(&b->notfull,NULL);b->readpos = 0;b->writepos = 0;}void put(struct prodcons *b,int data){pthread_mutex_lock(&b->lock);if((b->writepos + 1) % BUFFERSIZE == b->readpos){ pthread_cond_wait(&b->notfull,&b->lock);}b->buffer[b->writepos] = data;b->writepos++;if(b->writepos >= BUFFERSIZE)b->writepos = 0;pthread_cond_signal(&b->notempty);pthread_mutex_unlock(&b->lock);}int get(struct prodcons *b){int data;pthread_mutex_lock(&b->lock);if(b->writepos == b->readpos){pthread_cond_wait(&b->notempty,&b->lock);}data = b->buffer[b->readpos];b->readpos++;if(b->readpos >= BUFFERSIZE)b->readpos = 0;pthread_cond_signal(&b->notfull);pthread_mutex_unlock(&b->lock);return data;}struct prodcons buffer;void *producer1(void *data){int n;for(n = 0;n < 10000;n++){//printf("%d\n",n);printf("producer1 is writing\n");put(&buffer,n);}put(&buffer,OVER);return NULL;}void *producer2(void *data){int n;for(n = 0;n < 10000;n++){//printf("%d\n",n);printf("producer2 is writing\n");put(&buffer,n);}put(&buffer,OVER);return NULL;}void *consumer1(void * data){int d;while(1){d = get(&buffer);if(d == OVER)break;//printf("%d\n",d);printf("consumer1 is reading\n");}return NULL;}void *consumer2(void * data){int d;while(1){d = get(&buffer);if(d == OVER)break;//printf("%d\n",d);printf("consumer2 is reading\n");}return NULL;}int main(void){pthread_t writer1,reader1,writer2,reader2;void *retval;init(&buffer);pthread_create(&writer1,NULL,producer1,0);pthread_create(&reader1,NULL,consumer1,0);pthread_create(&writer2,NULL,producer2,0);pthread_create(&reader2,NULL,consumer2,0);pthread_join(writer1,&retval);pthread_join(reader1,&retval);pthread_join(writer2,&retval);pthread_join(reader2,&retval);return 0;}。

读者写者问题实验报告

读者写者问题实验报告

读者写者问题实验报告引言读者写者问题是计算机科学中经典的同步问题之一,它涉及多线程编程中的资源竞争与同步机制。

通过对读者写者问题的研究,我们可以深入理解线程同步的重要性,并掌握解决并发编程中可能出现的竞争条件和死锁等问题的方法。

在本实验中,我们将设计并实现一个简单的读者写者问题的解决方案,并通过模拟多个读者和写者的并发访问来验证方案的正确性和效果。

问题描述读者写者问题可描述为:有一共享资源(如文件、数据库等),读者可同时访问共享资源进行读取操作,但写者在进行写入操作时,不可同时被其他任何读者或写者访问。

读者和写者的并发访问需要由线程同步机制来保证共享资源的一致性和完整性。

实验设计与实现为了解决读者写者问题,我们需要考虑以下几个关键点:1. 共享资源的访问控制我们可以使用互斥量(Mutex)来实现对共享资源的访问控制。

当一个线程访问共享资源时,它需要先获得互斥量的锁,如果锁已被其他线程占用,则线程进入等待状态,直到锁可用。

一旦线程完成对共享资源的访问,它将释放锁,以便其他线程继续访问。

2. 读者与写者的优先级在读者写者问题中,我们往往需要设定某个优先级规则,以确定读者和写者之间的调度顺序。

一种常见的策略是给予写者优先级,即当一个写者在等待访问共享资源时,其他读者都必须等待。

这样做是为了避免写者长时间等待,以免造成饥饿问题。

3. 记录读者和写者的数量为了控制读者和写者的并发访问,我们需要记录当前同时访问共享资源的读者和写者的数量。

我们可以使用整数变量来记录读者和写者的数量,并通过信号量来保证对这些计数变量的互斥访问。

4. 同步机制的设计在实现读者写者问题的解决方案时,我们需要考虑如何合理地使用互斥量和信号量,并结合优先级规则来实现读者和写者的同步。

这需要通过仔细的设计和调试来确保解决方案的正确性。

实验结果与分析我们基于上述设计实现了一个读者写者问题的解决方案,并进行了多次仿真实验。

实验环境•操作系统:Windows 10•编程语言:C++•编译器:GCC实验步骤1.编写读者和写者线程的代码,其中涉及到对共享资源的读取和写入操作,以及对计数变量和互斥量的访问操作。

在linux下实现读者写者问题源代码

在linux下实现读者写者问题源代码

在linux下实现读者写者问题源代码读者写者问题是计算机科学中的一个经典同步问题,用于描述多个读者和写者对共享资源的访问。

在这个问题中,多个读者可以同时读取共享资源,但是写者在写入共享资源时必须独占访问。

在Linux下,我们可以使用线程和互斥锁来实现读者写者问题。

下面是一个简单的源代码示例:```c#include <stdio.h>#include <stdlib.h>#include <pthread.h>#define READERS_COUNT 5#define WRITERS_COUNT 2pthread_mutex_t mutex;pthread_cond_t cond_reader, cond_writer;int readers = 0;int writers = 0;void *reader(void *arg) {int id = *(int *)arg;while (1) {pthread_mutex_lock(&mutex);while (writers > 0) {pthread_cond_wait(&cond_reader, &mutex); }readers++;pthread_mutex_unlock(&mutex);// 读取共享资源printf("Reader %d is reading\n", id);pthread_mutex_lock(&mutex);readers--;if (readers == 0) {pthread_cond_signal(&cond_writer);}pthread_mutex_unlock(&mutex);}pthread_exit(NULL);}void *writer(void *arg) {int id = *(int *)arg;while (1) {pthread_mutex_lock(&mutex);while (readers > 0 || writers > 0) {pthread_cond_wait(&cond_writer, &mutex); }writers++;pthread_mutex_unlock(&mutex);// 写入共享资源printf("Writer %d is writing\n", id);pthread_mutex_lock(&mutex);writers--;pthread_cond_signal(&cond_writer);pthread_cond_broadcast(&cond_reader);pthread_mutex_unlock(&mutex);}pthread_exit(NULL);}int main() {pthread_t readers[READERS_COUNT];pthread_t writers[WRITERS_COUNT];int reader_ids[READERS_COUNT];int writer_ids[WRITERS_COUNT];pthread_mutex_init(&mutex, NULL);pthread_cond_init(&cond_reader, NULL);pthread_cond_init(&cond_writer, NULL);// 创建读者线程for (int i = 0; i < READERS_COUNT; i++) {reader_ids[i] = i + 1;pthread_create(&readers[i], NULL, reader, &reader_ids[i]); }// 创建写者线程for (int i = 0; i < WRITERS_COUNT; i++) {writer_ids[i] = i + 1;pthread_create(&writers[i], NULL, writer, &writer_ids[i]); }// 等待线程结束for (int i = 0; i < READERS_COUNT; i++) {pthread_join(readers[i], NULL);}for (int i = 0; i < WRITERS_COUNT; i++) {pthread_join(writers[i], NULL);}pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond_reader);pthread_cond_destroy(&cond_writer);return 0;}```在这个源代码中,我们使用了互斥锁(`pthread_mutex_t`)和条件变量(`pthread_cond_t`)来实现读者写者问题的同步。

操作系统读者写者实验报告

操作系统读者写者实验报告

操作系统读者写者实验报告一、实验目的通过实验理解读者写者问题的实现原理,掌握相关的同步机制,实现读者写者问题的经典解法,并对比不同解法的优缺点。

二、实验原理1.读者写者问题读者写者问题是指在多个线程同时读写一个共享数据的情况下可能出现的问题。

其问题的核心在于多个读线程可以同时读,但只能有一个写线程能够写,并且在写操作过程中不能有任何的读操作。

2.互斥与同步为了解决读者写者问题,在多线程并发读写共享数据时,需要使用互斥与同步机制来保证数据的完整性和一致性。

-互斥:通过锁机制来保证只允许一个线程进入临界区,其他线程需要等待锁的释放。

-同步:通过信号量等机制来保证线程按照一定顺序执行。

三、实验步骤本次实验中将实现两个版本的读者写者问题解决方案:一是使用互斥锁和条件变量,二是使用信号量。

1.使用互斥锁和条件变量(1)定义全局变量和互斥锁:共享数据、读者数目、互斥锁、写者条件变量、读者条件变量。

(2)初始化互斥锁和条件变量。

(3)写者线程的实现:获取互斥锁,判断当前是否有读者或写者,如果有则等待条件变量,然后进行写操作,释放互斥锁。

(4)读者线程的实现:获取互斥锁,判断是否有写者,如果有则等待条件变量,否则增加读者数目并释放互斥锁,进行读操作。

(5)测试程序的运行并输出结果。

2.使用信号量(1)定义全局变量和信号量:共享数据、读者信号量、写者信号量、用于保护读者数目和写者数目的互斥信号量。

(2)初始化信号量和互斥信号量。

(3)写者线程的实现:首先获取写者互斥信号量,然后获取写者信号量,进行写操作,释放写者信号量和写者互斥信号量。

(4)读者线程的实现:首先获取读者互斥信号量,然后增加读者数目,如果是第一个读者则获取写者信号量,然后进行读操作,释放读者信号量和读者互斥信号量,如果是最后一个读者则释放写者信号量。

(5)测试程序的运行并输出结果。

四、实验结果与分析通过对比两种解决方案,可以得出以下结论:1.使用互斥锁和条件变量的解决方案相对较为简单,但可能存在饥饿问题,即可能会导致一些线程一直无法访问共享资源。

操作系统读者写者实验报告

操作系统读者写者实验报告

《操作系统原理》课程设计课程设计起止时间:2009年11月30日至12月11日指导教师:成绩:课程设计成绩评定表一.设计说明(四号,宋体,加粗)通过学习操作系统,与之前的语句基础相结合,用C语言来编写读者写着问题。

读者写者问题(read—write problem)是一个经典的并发程序设计问题。

有两组并发进程:读者和写者,共享一个问题F,要求:(1)允许多个读者可同时对之执行读操作;(2)只允许一个写者往文件中写信息;(3)任一写者在完成写操作之前不允许其他读者或者写者工作;(4)写者执行写操作前,应让已有的写者和读者全部退出。

二.工作原理(四号,宋体,加粗)读者和写者问题是典型是经典的进程同步问题,进程同步任务是使并发的诸进程之间有效的共享资源,相互合作,从而保证程序的可再现性。

在读者—写者问题中,允许多个读者同时读一个数据对象,因为读文件不会使数据发生混乱,但绝不允许一个写者进程与其他读者进程或写者进程同时访问该数据对象。

文件是诸进程能互斥访问临界资源,读者进程和写者进程,写者进程和写者进程之间的互斥。

在读者进程中,可以有多个读者在读数据库,在读者进程的计数要互斥,以免发生错误,同时注意当第一个读者进程读时,一定要封锁写者进程。

当读者进程逐渐撤离时,也要针对计数变量进行互斥操作,若当前为最后一个读者进程时,读完后,则唤醒写者进程。

当写者进程在进行写操作时,可以封锁其他读者或写者进程,当写操作完成时,唤醒其他读者或写者进程。

所以分析了以下4种可能发生的情况:第 1 种情况: 读者的优先权比写者高,而且,不用调配。

所有读者的优先权都比写者的优先权高,而且,不用调配。

一个读者需要等待的唯一情况是,一个写者已经占用了文件。

一个写者可以取得文件的条件是,没有一个读者处在等待状态或正在读文件。

允许读者们结盟,以便能长期占用文件,而禁止写者的写。

第 2 种情况: 在一个读者已经占有了文件的时候,全体读者的优先权才比写者高。

多线程编程实验报告

多线程编程实验报告

一、实验目的1. 理解多线程编程的基本概念和原理。

2. 掌握多线程的创建、同步、通信和调度等关键技术。

3. 通过实验加深对多线程编程的理解,提高编程能力。

二、实验环境硬件:PC机软件:VMware虚拟机、Linux系统、C/C++编译器三、实验内容1. 多线程创建与运行2. 线程同步与互斥3. 线程通信与协作4. 线程调度与优先级5. 生产者-消费者问题四、实验步骤1. 多线程创建与运行(1)创建线程:使用pthread_create函数创建线程,指定线程的入口函数、参数、线程属性等。

(2)线程运行:编写线程入口函数,实现线程需要执行的任务。

(3)线程结束:在线程入口函数中执行任务后,使用pthread_exit函数结束线程。

2. 线程同步与互斥(1)互斥锁:使用pthread_mutex_lock和pthread_mutex_unlock函数实现互斥锁,保证同一时刻只有一个线程访问共享资源。

(2)条件变量:使用pthread_cond_wait和pthread_cond_signal函数实现条件变量,实现线程间的同步与协作。

(3)读写锁:使用pthread_rwlock_rdlock和pthread_rwlock_wrlock函数实现读写锁,允许多个线程同时读取共享资源,但只有一个线程可以写入。

3. 线程通信与协作(1)线程间通信:使用pthread_cond_signal、pthread_cond_broadcast、pthread_barrier_wait等函数实现线程间的通信。

(2)线程协作:使用pthread_barrier_init、pthread_barrier_wait函数实现线程间的协作,确保所有线程到达某个点后再继续执行。

4. 线程调度与优先级(1)线程调度:了解操作系统的线程调度算法,如时间片轮转、优先级调度等。

(2)线程优先级:使用pthread_setschedparam函数设置线程的调度策略和优先级。

多线程读者写者优先实验报告

多线程读者写者优先实验报告

实验三 多线程编程 实验报告实验目的要求在每个线程创建、 发出读写操作申请、 开始读写操作和结束读写操作时分别显行提示信息,以确信所有处理都遵守相应的读写操作限制。

是读者还是写者, 以及读写操作的开始时间和持续时间。

每行测试数据包括四个字段, 段间用空格分隔。

第一字段为一个正整数,表示线程序号。

第二字段表示相应线程角色,表示读者是, W 表示写者。

第三字段为一个正数,表示读写操作的开始时间。

线程创建后, 延时相应时间(单位为秒)后发出对共享资源的读写申请。

第四字段为一个正数, 操作的持续时间。

当线程读写申请成功后, 开始对共享资源的读写操作, 该操作持续相应时 1、 熟悉多线程编程2、 熟悉使用信号量机制解决进程同步问题实验内容在 Windows 2000 环境下,创建一个包含 n 个线程的控制台进程。

用这n 个线程来表 示 n 个读者或写者。

每个线程按相应测试数据文件的要求, 进行读写操作。

请用信号量机制 分别实现读者优先和写者优先的读者 -写者问题。

读者优先: 如果一个读者申请进行读操作时已有另一读者正在进行读操作,则该读者可直接 开始读操作。

写者优先: 如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。

实验条件 1、为每个学生提供一台具有 WINDOWS 2000/NT/XP 操作系统的计算机;2、实验机器要求安装 Visual C++ 6.0 编程平台;3、实验要求一人一机。

四、运行结果显示要求1、 2、 测试数据文件格式:测试数据文件包括 n 行测试数据,分别描述创建的 n个线程各字 表示读写间后结束,并释放共享资源。

下面是一个测试数据文件的例子:若有可能请在图形方式下,将读、写者线程执行情况用图形动画显示五 实验源程序#include<windows.h> #include<conio.h> #include<stdlib.h> #include<fstream.h> #include<io.h> #include<string.h>#include<stdio.h>int writecount=0;CRITICAL_SECTION RP_Write;// CRITICAL_SECTION RP_Write_Reader; // 临界资源 int choice=0;struct ThreadInfoint serial;// 线程序号char entity;// 线程类别double delay;// 线程延迟时间,即开始时间 double persist;// 线程读写操作时间};void RP_ReaderThread (void *p){HANDLE h_Mutex; // HANDLE s_Mutex;#define READER 'R'#define WRITER 'W'//读者 //写者 #define INTE_PER_SEC 1000 #define MAX_THREAD_NUM 64//定义每秒中断的次数 //定义最大线程数 #define MAX_FILE_NUM 32 #define MAX_STR_LEN 32 //定义最大文件数目 // int readcount=0;// 3、 // 临界资源s_Mutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex_for_readORwriter");h_Mutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex_for_readcount");DWORD wait_for_mutex;DWORD m_delay;DWORD m_persist;int m_serial; m_serial=((ThreadInfo*)(p))->serial;m_delay=(DWORD)(((ThreadInfo*)(p))->delay * INTE_PER_SEC);m_persist=(DWORD)(((ThreadInfo*)(p))->persist * INTE_PER_SEC); Sleep(m_delay); //printf(" 读线程 %d 发出请求 .\n",m_serial);cout<<" 读线程 "<<m_serial<<" 发出读请求 "<<endl;if (choice==1){EnterCriticalSection(&RP_Write_Reader); } wait_for_mutex=WaitForSingleObject(h_Mutex,-1);wait_for_mutex=WaitForSingleObject(s_Mutex,-1); if(readcount==0){EnterCriticalSection(&RP_Write); }readcount++;ReleaseMutex(h_Mutex);if (choice==1){LeaveCriticalSection(&RP_Write_Reader); } ReleaseMutex(s_Mutex);//printf(" 读进程 %d 开始读文件 .\n",m_serial); cout<<" 读线程 "<<m_serial<<" 开始读文件 "<<endl; Sleep(m_persist);//printf(" 读进程 %d 结束读文件 .\n",m_serial); cout<<" 读线程 "<<m_serial<<" 结束读文件 ."<<endl; wait_for_mutex=WaitForSingleObject(h_Mutex,-1); readcount--; if(readcount==0){LeaveCriticalSection(&RP_Write);}ReleaseMutex(h_Mutex);// // //void RP_WriteThread(void *p) {// // // DWORD m_delay;DWORD m_persist;int m_serial;HANDLE s_Mutex;DWORD wait_for_mutex;s_Mutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex_for_readORwriter"); m_serial=((ThreadInfo*)(p))->serial;m_delay=(DWORD)(((ThreadInfo*)(p))->delay*INTE_PER_SEC);m_persist=(DWORD)(((ThreadInfo*)(p))->persist*INTE_PER_SEC);Sleep(m_delay);/ / cout<<" 写进程"<<m_serial<<" 发出写请求***"<<endl; if (choice==1){EnterCriticalSection(&RP_Write_Reader);}wait_for_mutex=WaitForSingleObject(s_Mutex,-1); EnterCriticalSection(&RP_Write);cout<<" 写进程"<<m_serial<<" 开始写文件"<<endl;Sleep(m_persist);/ / }cout<<" 写进程"<<m_serial<<" 结束写文件"<<endl; LeaveCriticalSection(&RP_Write);if (choice==1){LeaveCriticalSection(&RP_Write_Reader);}ReleaseMutex(s_Mutex);void ReadPriority(char*file) {DWORD n_thread=0;DWORD thread_ID;DWORD wait_for_all;HANDLE h_Mutex;HANDLE s_MUTEX;h_Mutex=CreateMutex(NULL,FALSE,"mutex_for_readcount");s_MUTEX=CreateMutex(NULL,FALSE,"mutex_for_readerORwriter");HANDLE h_Thread[MAX_THREAD_NUM];ThreadInfo thread_info[MAX_THREAD_NUM];readcount=0;InitializeCriticalSection(&RP_Write);InitializeCriticalSection(&RP_Write_Reader); ifstream inFile;inFile.open(file); while(inFile){inFile>>thread_info[n_thread].serial;cout<<thread_info[n_thread].serial<<'\t';inFile>>thread_info[n_thread].entity;cout<<thread_info[n_thread].entity<<'\t';inFile>>thread_info[n_thread].delay;cout<<thread_info[n_thread].delay<<'\t';inFile>>thread_info[n_thread].persist;cout<<thread_info[n_thread++].persist<<'\t'; inFile.get();cout<<endl;}inFile.close();for(int i=0;i<(int)(n_thread);i++){if(thread_info[i].entity==READER||thread_info[i].entity=='R'){h_Thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(RP_ReaderThread),&thread_info[i],0,&thread_ID);}else{h_Thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(RP_WriteThread),&thread_info[i],0,&thread_ID);}}wait_for_all=WaitForMultipleObjects(n_thread,h_Thread,TRUE,-1);cout<<" 所有线程运行完毕"<<endl;}int main(){int n;cout<<"输入你的选择:\n1:读者优先\n2:读者优先\n3:退出\n"<<endl;cin>>n;while(n!=3){switch (n){case 1:choice=0;Read Priority("1.txt");break;case 2:choice=1;Read Priority("1.txt");break;defaultbreak;}cout<<"输入你的选择:\n1:读者优先\n2:写者优先\n3:退出\n"<<endl; cin>>n;}system(" PAUSE");return 0;六实验结果七实验总结由于此实验用到API函数,自己不知道,所以上网搜索一些关于线程的查阅一些参API函数,又通过考书,逐渐掌握了多线程编程及其函数应用。

linux多线程实验报告

linux多线程实验报告

实验八Linux多线程实验报告撰写人专业班级学号完成时间。

一、实验目的1、了解什么是多线程,熟悉LINUX的多线程机制;2、掌握利用信号处理Linux多线程的同步问题;3、掌握利用信号量处理Linux多线程的互斥问题;4、运用Linux多线程的同步机制和互斥机制实现生产者消费者的编程。

二、实验内容1.“生产者-消费者”问题如下:有一个有限缓冲区和两个线程:生产者和消费者。

他们分别不停地把产品放入缓冲区、从缓冲区中拿走产品。

一个生产者在缓冲区满的时候必须等待,一个消费者在缓冲区空的时候也必须等待。

另外,因为缓冲区是临界资源,所以.. v .. .生产者和消费者之间必须互斥执行。

它们之间的关系如图1所示。

现在要求使用共享内存来模拟有限缓冲区,并且使用信号量来解决“生产者-消费者”问题中的同步和互斥问题。

生产者消费者11234N1 生产者和消费者问题描述2. 问题描述:假设有五位哲学家围坐在一张圆形餐桌旁,做以下两件事情之一:吃饭,或者思考。

吃东西的时候,他们就停止思考,思考的时候也停止吃东西。

餐桌中间有一大碗意大利面,每两个哲学家之间有一只餐叉。

因为用一只餐叉很难吃到意大利面,所以假设哲学家必须用两只餐叉吃东西。

他们只能使用自己左右手边的那两只餐叉。

请用Linux线程编程解决。

2 哲学家进餐问题示意图三、实验过程与结果操作过程错误解决方法实步骤一:在不同的.. v .. .验1 编写producer_customer.c的文件编译器中for循环的用法不太一样,在这里最好不要使用for(inti=0;;)最好在外声明int i在for循环里直接写i=0步骤二:编译代码并且运行代码步骤三:运行完毕后,显示以下代码:.. v .. .生产者消费者先后生产数据以及取出数据,此程序中设置了两个消费者两个生产者,交替进行生产数据消费数据。

实验步骤一:编写philosopher.c的文件.. v .. .2步骤二:编译代码并且运行代码步骤三:.. v .. .实验代码实验一:#include <stdio.h> #include <stdlib.h> #include <unistd.h>.. v .. .#include <time.h>#include <sys/ipc.h>#include <sys/shm.h>#include <sys/sem.h>#include <sys/types.h>#define MAX_BUFFER_SIZE 10#define SHM_MODE 0600#define SEM_MODE 0600#define SEM_FULL 0#define SEM_EMPTY 1#define MUTEX 2/*#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)// union semun is defined by including <sys/sem.h>.. v .. .#else// according to X/OPEN we have to define it ourselvesunion semun{int val;struct semid_ds *buf;unsigned short *array;};#endifunion semun su;//sem union,用于初始化信号量*/struct my_buffer{int head;int tail;.. v .. .char str[MAX_BUFFER_SIZE];int num; //缓冲区里字母数量int is_empty;};const int N_CONSUMER = 2;//消费者数量const int N_PRODUCER = 2;//生产者数量const int N_BUFFER = 10;//缓冲区容量const int N_WORKTIME = 10;//工作次数int shm_id = -1;int sem_id = -1;pid_t child;pid_t parent;//得到10以内的一个随机数int get_random().. v .. .{int digit;srand((unsigned)(getpid() + time(NULL)));digit = rand() % 10;return digit;}//得到A~Z的一个随机字母char getRandChar(){char letter;srand((unsigned)(getpid() + time(NULL)));letter = (char)((rand() % 26) + 'A');return letter;}.. v .. .//sem_id 表示信号量集合的id//sem_num 表示要处理的信号量在信号量集合中的索引//P操作void waitSem(int sem_id,int sem_num){struct sembuf sb;sb.sem_num = sem_num;sb.sem_op = -1;//表示要把信号量减一sb.sem_flg = SEM_UNDO;////第二个参数是sembuf [] 类型的,表示数组//第三个参数表示第二个参数代表的数组的大小if(semop(sem_id,&sb,1) < 0){perror("waitSem failed");exit(1);.. v .. .}}//V操作void sigSem(int sem_id,int sem_num){struct sembuf sb;sb.sem_num = sem_num;sb.sem_op = 1;sb.sem_flg = SEM_UNDO;//第二个参数是sembuf [] 类型的,表示数组//第三个参数表示第二个参数代表的数组的大小if(semop(sem_id,&sb,1) < 0){perror("sigSem failed");exit(1);.. v .. .}}//打印进程运行结果void printTime(){//打印时间time_t now;struct tm *timenow; //实例化tm结构指针time(&now);timenow = localtime(&now);printf("执行时间:%s ",asctime(timenow));}.. v .. .int main(int argc, char ** argv){shm_id = shmget(IPC_PRIVATE,MAX_BUFFER_SIZE,SHM_MODE); //申请共享内存if(shm_id < 0){perror("create shared memory failed");exit(1);}struct my_buffer *shmptr;shmptr = shmat(shm_id, 0, 0); //将申请的共享内存附加到申请通信的进程空间if (shmptr == (void*)-1){perror("add buffer to using process space failed!\n");.. v .. .exit(1);}if((sem_id = semget(IPC_PRIVATE,3,SEM_MODE)) < 0){ //创建三个信号量,SEM_EMPTY,SEM_FULL和MUTEXperror("create semaphore failed! \n");exit(1);}if(semctl(sem_id,SEM_FULL,SETVAL,0) == -1){ //将索引为0的信号量设置为0-->SEM_FULLperror("sem set value error! \n");exit(1);}if(semctl(sem_id,SEM_EMPTY,SETVAL,10) == -1){ //将索引为1的信号量设置为10-->SEM_EMPTY.. v .. .perror("sem set value error! \n");exit(1);}if(semctl(sem_id,MUTEX,SETVAL,1) == -1){ //将索引为3的信号量设置为1-->MUTEXperror("sem set value error! \n");exit(1);}shmptr -> head = 0;shmptr -> tail = 0;shmptr -> is_empty = 1;shmptr -> num = 0;int i;for(i = 0; i < N_PRODUCER; i++).. v .. .{parent = fork();if(parent < 0){perror("the fork failed");exit(1);}else if(parent == 0){shmptr = shmat(shm_id, 0, 0); //将申请的共享内存附加到申请通信的进程空间if (shmptr == (void*)-1){perror("add buffer to using process space failed!\n");.. v .. .exit(1);}int count = 0;int j;for(j = 0; j < N_WORKTIME; j++){waitSem(sem_id, SEM_EMPTY);waitSem(sem_id, MUTEX);sleep(get_random());printf("-------------------------------------------------------------\ n");printf("我是第%d 个生产者进程,PID = %d\n", i + 1, getpid());/*生产产品*/.. v .. .char c = getRandChar(); //随机获取字母shmptr -> str[shmptr->tail] = c;shmptr -> tail = (shmptr->tail + 1) % MAX_BUFFER_SIZE;shmptr -> is_empty = 0; //写入新产品shmptr -> num++;/*打印输出结果*/printTime(); //程序运行时间int p;printf("缓冲区数据(%d个):",shmptr -> num); //打印缓冲区中的数据p = (shmptr->tail-1 >= shmptr->head) ? (shmptr->tail-1) : (shmptr->tail-1 + MAX_BUFFER_SIZE);for (p; !(shmptr -> is_empty) && p >= shmptr -> head; p--){.. v .. .printf("%c", shmptr -> str[p % MAX_BUFFER_SIZE]);}printf("\t 生产者%d 放入'%c'. \n", i + 1, c);printf("-------------------------------------------------------------\ n");fflush(stdout);sigSem(sem_id, MUTEX);sigSem(sem_id, SEM_FULL);}//将共享段与进程之间解除连接shmdt(shmptr);exit(0);}.. v .. .}for(i = 0; i < N_CONSUMER; i++){child = fork();if(child < 0)//调用fork失败{perror("the fork failed");exit(1);}else if(child == 0){int count = 0;shmptr = shmat(shm_id, 0, 0); //将申请的共享内存附加到申请通信的进程空间.. v .. .if (shmptr == (void*)-1){perror("add buffer to using process space failed!\n");exit(1);}int j;for(j = 0; j < N_WORKTIME; j++){waitSem(sem_id, SEM_FULL);waitSem(sem_id, MUTEX);sleep(get_random());printf("-------------------------------------------------------------\ n");.. v .. .printf("我是第%d 个消费者进程,PID = %d\n", i + 1, getpid());/*消费数据*/char lt = shmptr -> str[shmptr -> head];shmptr -> head = (shmptr -> head + 1) % MAX_BUFFER_SIZE;shmptr -> is_empty = (shmptr->head == shmptr->tail); //shmptr -> num--;/*打印输出结果*/printTime(); //程序运行时间int p;printf("缓冲区数据(%d个):",shmptr -> num); //打印缓冲区中的数据p = (shmptr -> tail - 1 >= shmptr -> head) ? (shmptr -> tail-1) : (shmptr -> tail - 1 + MAX_BUFFER_SIZE);for (p; !(shmptr -> is_empty) && p >= shmptr -> head; p--).. v .. .{printf("%c", shmptr -> str[p % MAX_BUFFER_SIZE]);}printf("\t 消费者%d 取出'%c'. \n", i + 1, lt);printf("-------------------------------------------------------------\ n");fflush(stdout);sigSem(sem_id,MUTEX);sigSem(sem_id,SEM_EMPTY);}//将共享段与进程之间解除连接shmdt(shmptr);exit(0);.. v .. .}}//主进程最后退出while (wait(0) != -1);//将共享段与进程之间解除连接shmdt(shmptr);//对共享内存区执行控制操作shmctl(shm_id,IPC_RMID,0);//当cmd为IPC_RMID时,删除该共享段shmctl(sem_id,IPC_RMID,0);printf("主进程运行结束!\n");fflush(stdout);exit(0);return 0;}.. v .. .实验二:#include<sys/types.h>#include<unistd.h>#include<stdlib.h>#include<stdio.h>#include<pthread.h>#include<semaphore.h>#include<time.h>#define N 5 //哲学家数量#define LEFT(i) (i+N-1)%N //左手边哲学家编号#define RIGHT(i) (i+1)%N //右手边哲家编号.. v .. .#define HUNGRY 0 //饥饿#define THINKING 1 //思考#define EATING 2 //吃饭#define U_SECOND 1000000 //1秒对应的微秒数pthread_mutex_t mutex; //互斥量int state[N]; //记录每个哲学家状态//每个哲学家的思考时间,吃饭时间,思考开始时间,吃饭开始时间clock_t thinking_time[N], eating_time[N], start_eating_time[N], start_thinking_time[N];//线程函数void *thread_function(void *arg);.. v .. .int main(){pthread_mutex_init(&mutex, NULL);pthread_t a,b,c,d,e;//为每一个哲学家开启一个线程,传递哲学家编号pthread_create(&a,NULL,thread_function,"0");pthread_create(&b,NULL,thread_function,"1");pthread_create(&c,NULL,thread_function,"2");pthread_create(&d,NULL,thread_function,"3");pthread_create(&e,NULL,thread_function,"4");//初始化随机数种子srand((unsigned int)(time(NULL)));while(1).. v .. .{;}}void *thread_function(void *arg){char *a = (char *)arg;int num = a[0] - '0'; //根据传递参数获取哲学家编号int rand_time;while(1){//关键代码加锁pthread_mutex_lock(&mutex);.. v .. .//如果该哲学家处于饥饿并且左右两位哲学家都没有在吃饭就拿起叉子吃饭if(state[num] == HUNGRY && state[LEFT(num)] != EATING && state[RIGHT(num)] != EATING){state[num] = EATING;start_eating_time[num] = clock(); //记录开始吃饭时间eating_time[num] = (rand() % 5 + 5) * U_SECOND; //随机生成吃饭时间//输出状态printf("state: %d %d %d %d %d\n",state[0],state[1],state[2],state[3],state[4]);//printf("%d is eating\n",num);}.. v .. .else if(state[num] == EATING){//吃饭时间已到,开始思考if(clock() - start_eating_time[num] >= eating_time[num]) //{state[num] = THINKING;//printf("%d is thinking\n",num);printf("state: %d %d %d %d %d\n",state[0],state[1],state[2],state[3],state[4]);start_thinking_time[num] = clock(); //记录开始思考时间thinking_time[num] = (rand() % 10 + 10) * U_SECOND; //随机生成思考时间}}.. v .. .else if(state[num] == THINKING){//思考一定时间后,哲学家饿了,需要吃饭if(clock() - start_thinking_time[num] >= thinking_time[num]){state[num] = HUNGRY;printf("state: %d %d %d %d %d\n",state[0],state[1],state[2],state[3],state[4]);// printf("%d is hungry\n",num);}}pthread_mutex_unlock(&mutex);}}.. v .. .四、实验小结生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。

实验3--读者-写者问题与进程同步

实验3--读者-写者问题与进程同步

实验3 读者/写者问题与进程同步3.1 实验目的理解临界区和进程互斥的概念,掌握用信号量和PV操作实现进程互斥的方法。

3.2 实验要求在linux环境下编写一个控制台应用程序,该程序运行时能创建N个线程〔或者进程〕,其中既有读者线程又有写者线程,它们按照事先设计好的测试数据进行读写操作。

请用信号量和PV操作实现读者/写者问题。

读者/写者问题的描述如下:有一个被许多进程共享的数据区,这个数据区可以是一个文件,或者主存的一块空间〔比方一个数组或一个变量〕,甚至可以是一组处理器寄存器。

有一些只读取这个数据区的进程〔reader〕和一些只往数据区中写数据的进程〔writer〕。

以下假设共享数据区是文件。

这些读者和写者对数据区的操作必须满足以下条件:读—读允许;读—写互斥;写—写互斥。

这些条件具体来说就是:〔1〕任意多的读进程可以同时读这个文件;〔2〕一次只允许一个写进程往文件中写;〔3〕如果一个写进程正在往文件中写,禁止任何读进程或写进程访问文件;〔4〕写进程执行写操作前,应让已有的写者或读者全部退出。

这说明当有读者在读文件时不允许写者写文件。

对于读者-写者问题,有三种解决方法:1、读者优先除了上述四个规则外,还增加读者优先的规定,当有读者在读文件时,对随后到达的读者和写者,要首先满足读者,阻塞写者。

这说明只要有一个读者活跃,那么随后而来的读者都将被允许访问文件,从而导致写者长时间等待,甚至有可能出现写者被饿死的情况。

2、写者优先除了上述四个规则外,还增加写者优先的规定,即当有读者和写者同时等待时,首先满足写者。

当一个写者声明想写文件时,不允许新的读者再访问文件。

3、无优先除了上述四个规则外,不再规定读写的优先权,谁先等待谁就先使用文件。

实验步骤算法分析有同学认为,可以将文件视为临界资源,使用临界资源的代码就构成临界区,为了对临界区进行管理,只需设置一个互斥信号量r_w_w,读或者写之前执行P(r_w_w),之后执行V(r_w_w)即可,从而得到图3-1所示的算法描述。

Linux实验报告 消费者与生产者 多线程

Linux实验报告 消费者与生产者 多线程
编号
LINUX实验报告
题 目linux高级程序设计
学生姓名指导教师学 院来自专业班级学 号
完成时间
实验3 Linux高级程序设计
1、实验目的
(1)了解Linux操作系统下应用程序开发流程
(2)掌握gun工具链的使用
(3)了解Linux高级编程技巧(例如IPC机制、系统调用等)
2、实验内容
(1)编写一个简单的C语言程序,编写Makefile文件。了解编译过程,并用gdb进行调试。
{
//缓冲区相关数据结构
int buffer[BUFFER_SIZE];
pthread_mutex_t lock;
int readpos, writepos;
pthread_cond_t notempty;
pthread_cond_t notfull;
};
void init(struct prodcons *b) {
printf("请选择下列操作:\n\n1.生产\n\n2.消费\n\n3.退出\n");
while(1)
{
int a;
scanf("%d",&i);
if(i==1)
{
printf("请输入要生产的数量a\n");
scanf("%d",&a);
for(i=m;i<m+a;i++)array[i]=1;
对于实验2:
a)编写一个生产者-消费者程序组,要求同时支持多个生产者和消费者,生产者与消费者使用Message Queue或shared Memory或者Pipe File机制进行通信
设计方案:

linux多线程实验报告

linux多线程实验报告

1 / 18实验八 Linux 多线程实验报告撰写人专业班级 学号姓名 完成时间。

一、 实验目的1、 了解什么是多线程,熟悉LINUX 的多线程机制;2、 掌握利用信号处理Linux 多线程的同步问题;3、掌握利用信号量处理Linux 多线程的互斥问题;4、 运用Linux 多线程的同步机制和互斥机制实现生产者消费者的编程。

二、 实验内容1. “生产者-消费者”问题如下:有一个有限缓冲区和两个线程:生产者和消费者。

他们分别不停地把产品放入缓冲区、从缓冲区中拿走产品。

一个生产者在缓冲区满的时候必须等待,一个消费者在缓冲区空的时候也必须等待。

另外,因为缓冲区是临界资源,所以生产者和消费者之间必须互斥执行。

它们之间的关系如图1所示。

现在要求使用共享内存来模拟有限缓冲区,并且使用信号量来解决“生产者-消费者”问题中的同步和互斥问题。

生产者和消费者问题描述2. 问题描述:假设有五位哲学家围坐在一张圆形餐桌旁,做以下两件事情之一:吃饭,或者思考。

吃东西的时候,他们就停止思考,思考的时候也停止吃东西。

餐桌中间有一大碗意大利面,每两个哲学家之间有一只餐叉。

因为用一只餐叉很难吃到意大利面,所以假设哲学家必须用两只餐叉吃东西。

他们只能使用自己左右手边的那两只餐叉。

请用Linux 线程编程解决。

2 哲学家进餐问题示意图三、实验过程与结果操作过程错误解决方法实验1 步骤一:编写producer_customer.c的文件在不同的编译器中for循环的用法不太一样,在这里最好不要使用for(inti=0;;)最好在外声明inti在for循环里直接写i=02/ 18步骤二:编译代码并且运行代码步骤三:运行完毕后,显示以下代码:生产者消费者先后生产数据以及取出数据,此程序中设置了两个消费者两个生产者,交替进行生产数据消费数据。

实验步骤一:编写philosopher.c的文件3/ 182步骤二:编译代码并且运行代码步骤三:4/ 18实验代码实验一:#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <time.h>#include <sys/ipc.h>#include <sys/shm.h>#include <sys/sem.h>#include <sys/types.h>#define MAX_BUFFER_SIZE 105/ 18#define SHM_MODE 0600#define SEM_MODE 0600#define SEM_FULL 0#define SEM_EMPTY 1#define MUTEX 2/*#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)// union semun is defined by including <sys/sem.h>#else// according to X/OPEN we have to define it ourselvesunion semun{int val;struct semid_ds *buf;unsigned short *array;};#endifunion semun su;//sem union,用于初始化信号量*/struct my_buffer{int head;int tail;char str[MAX_BUFFER_SIZE];int num; //缓冲区里字母数量int is_empty;};const int N_CONSUMER = 2;//消费者数量const int N_PRODUCER = 2;//生产者数量const int N_BUFFER = 10;//缓冲区容量6/ 18const int N_WORKTIME = 10;//工作次数int shm_id = -1;int sem_id = -1;pid_t child;pid_t parent;//得到10以内的一个随机数int get_random(){int digit;srand((unsigned)(getpid() + time(NULL)));digit = rand() % 10;return digit;}//得到A~Z的一个随机字母char getRandChar(){char letter;srand((unsigned)(getpid() + time(NULL)));letter = (char)((rand() % 26) + 'A');return letter;}//sem_id 表示信号量集合的 id//sem_num 表示要处理的信号量在信号量集合中的索引//P操作void waitSem(int sem_id,int sem_num){struct sembuf sb;sb.sem_num = sem_num;sb.sem_op = -1;//表示要把信号量减一7/ 18sb.sem_flg = SEM_UNDO;////第二个参数是 sembuf [] 类型的,表示数组//第三个参数表示第二个参数代表的数组的大小if(semop(sem_id,&sb,1) < 0){perror("waitSem failed");exit(1);}}//V操作void sigSem(int sem_id,int sem_num){struct sembuf sb;sb.sem_num = sem_num;sb.sem_op = 1;sb.sem_flg = SEM_UNDO;//第二个参数是 sembuf [] 类型的,表示数组//第三个参数表示第二个参数代表的数组的大小if(semop(sem_id,&sb,1) < 0){perror("sigSem failed");exit(1);}}//打印进程运行结果void printTime(){//打印时间time_t now;struct tm *timenow; //实例化tm结构指针time(&now);8/ 18timenow = localtime(&now);printf("执行时间: %s ",asctime(timenow));}int main(int argc, char ** argv){shm_id = shmget(IPC_PRIVATE,MAX_BUFFER_SIZE,SHM_MODE); //申请共享内存if(shm_id < 0){perror("create shared memory failed");exit(1);}struct my_buffer *shmptr;shmptr = shmat(shm_id, 0, 0); //将申请的共享内存附加到申请通信的进程空间if (shmptr == (void*)-1){perror("add buffer to using process space failed!\n");exit(1);}if((sem_id = semget(IPC_PRIVATE,3,SEM_MODE)) < 0){ //创建三个信号量,SEM_EMPTY,SEM_FULL和MUTEXperror("create semaphore failed! \n");exit(1);}if(semctl(sem_id,SEM_FULL,SETVAL,0) == -1){ //将索引为0的信号量设置为0-->SEM_FULLperror("sem set value error! \n");9/ 18exit(1);}if(semctl(sem_id,SEM_EMPTY,SETVAL,10) == -1){ //将索引为1的信号量设置为10-->SEM_EMPTYperror("sem set value error! \n");exit(1);}if(semctl(sem_id,MUTEX,SETVAL,1) == -1){ //将索引为3的信号量设置为1-->MUTEXperror("sem set value error! \n");exit(1);}shmptr -> head = 0;shmptr -> tail = 0;shmptr -> is_empty = 1;shmptr -> num = 0;int i;for(i = 0; i < N_PRODUCER; i++){parent = fork();if(parent < 0){perror("the fork failed");exit(1);}else if(parent == 0){shmptr = shmat(shm_id, 0, 0); //将申请的共享内存附加到申请通信的进程空间10/ 18if (shmptr == (void*)-1){perror("add buffer to using process space failed!\n");exit(1);}int count = 0;int j;for(j = 0; j < N_WORKTIME; j++){waitSem(sem_id, SEM_EMPTY);waitSem(sem_id, MUTEX);sleep(get_random());printf("-------------------------------------------------------------\n");printf("我是第 %d 个生产者进程,PID = %d\n", i + 1, getpid());/*生产产品*/char c = getRandChar(); //随机获取字母shmptr -> str[shmptr->tail] = c;shmptr -> tail = (shmptr->tail + 1) % MAX_BUFFER_SIZE;shmptr -> is_empty = 0; //写入新产品shmptr -> num++;/*打印输出结果*/printTime(); //程序运行时间int p;printf("缓冲区数据(%d个):",shmptr -> num); //打印缓冲区中的数据p = (shmptr->tail-1 >= shmptr->head) ? (shmptr->tail-1) :(shmptr->tail-1 + MAX_BUFFER_SIZE);11/ 18for (p; !(shmptr -> is_empty) && p >= shmptr -> head; p--){printf("%c", shmptr -> str[p % MAX_BUFFER_SIZE]);}printf("\t 生产者 %d 放入 '%c'. \n", i + 1, c);printf("-------------------------------------------------------------\n");fflush(stdout);sigSem(sem_id, MUTEX);sigSem(sem_id, SEM_FULL);}//将共享段与进程之间解除连接shmdt(shmptr);exit(0);}}for(i = 0; i < N_CONSUMER; i++){child = fork();if(child < 0)//调用fork失败{perror("the fork failed");exit(1);}else if(child == 0){int count = 0;shmptr = shmat(shm_id, 0, 0); //将申请的共享内存附加到申请通信的12/ 18进程空间if (shmptr == (void*)-1){perror("add buffer to using process space failed!\n");exit(1);}int j;for(j = 0; j < N_WORKTIME; j++){waitSem(sem_id, SEM_FULL);waitSem(sem_id, MUTEX);sleep(get_random());printf("-------------------------------------------------------------\n");printf("我是第 %d 个消费者进程,PID = %d\n", i + 1, getpid());/*消费数据*/char lt = shmptr -> str[shmptr -> head];shmptr -> head = (shmptr -> head + 1) % MAX_BUFFER_SIZE;shmptr -> is_empty = (shmptr->head == shmptr->tail); //shmptr -> num--;/*打印输出结果*/printTime(); //程序运行时间int p;printf("缓冲区数据(%d个):",shmptr -> num); //打印缓冲区中的数据p = (shmptr -> tail - 1 >= shmptr -> head) ? (shmptr -> tail-1) :(shmptr -> tail - 1 + MAX_BUFFER_SIZE);for (p; !(shmptr -> is_empty) && p >= shmptr -> head; p--)13/ 18{printf("%c", shmptr -> str[p % MAX_BUFFER_SIZE]);}printf("\t 消费者 %d 取出 '%c'. \n", i + 1, lt);printf("-------------------------------------------------------------\n");fflush(stdout);sigSem(sem_id,MUTEX);sigSem(sem_id,SEM_EMPTY);}//将共享段与进程之间解除连接shmdt(shmptr);exit(0);}}//主进程最后退出while (wait(0) != -1);//将共享段与进程之间解除连接shmdt(shmptr);//对共享内存区执行控制操作shmctl(shm_id,IPC_RMID,0);//当cmd为IPC_RMID时,删除该共享段shmctl(sem_id,IPC_RMID,0);printf("主进程运行结束!\n");fflush(stdout);exit(0);return 0;}14/ 18实验二:#include<sys/types.h>#include<unistd.h>#include<stdlib.h>#include<stdio.h>#include<pthread.h>#include<semaphore.h>#include<time.h>#define N 5 //哲学家数量#define LEFT(i) (i+N-1)%N //左手边哲学家编号#define RIGHT(i) (i+1)%N //右手边哲家编号#define HUNGRY 0 //饥饿#define THINKING 1 //思考#define EATING 2 //吃饭#define U_SECOND 1000000 //1秒对应的微秒数pthread_mutex_t mutex; //互斥量int state[N]; //记录每个哲学家状态//每个哲学家的思考时间,吃饭时间,思考开始时间,吃饭开始时间clock_t thinking_time[N], eating_time[N], start_eating_time[N],start_thinking_time[N];//线程函数void *thread_function(void *arg);int main(){15/ 18pthread_mutex_init(&mutex, NULL);pthread_t a,b,c,d,e;//为每一个哲学家开启一个线程,传递哲学家编号pthread_create(&a,NULL,thread_function,"0");pthread_create(&b,NULL,thread_function,"1");pthread_create(&c,NULL,thread_function,"2");pthread_create(&d,NULL,thread_function,"3");pthread_create(&e,NULL,thread_function,"4");//初始化随机数种子srand((unsigned int)(time(NULL)));while(1){;}}void *thread_function(void *arg){char *a = (char *)arg;int num = a[0] - '0'; //根据传递参数获取哲学家编号int rand_time;while(1){//关键代码加锁pthread_mutex_lock(&mutex);//如果该哲学家处于饥饿并且左右两位哲学家都没有在吃饭就拿起叉子吃饭if(state[num] == HUNGRY && state[LEFT(num)] != EATING &&16/ 18state[RIGHT(num)] != EATING){state[num] = EATING;start_eating_time[num] = clock(); //记录开始吃饭时间eating_time[num] = (rand() % 5 + 5) * U_SECOND; //随机生成吃饭时间//输出状态printf("state: %d %d %d %d %d\n",state[0],state[1],state[2],state[3],state[4]);//printf("%d is eating\n",num);}else if(state[num] == EATING){//吃饭时间已到,开始思考if(clock() - start_eating_time[num] >= eating_time[num]) //{state[num] = THINKING;//printf("%d is thinking\n",num);printf("state: %d %d %d %d %d\n",state[0],state[1],state[2],state[3],state[4]);start_thinking_time[num] = clock(); //记录开始思考时间thinking_time[num] = (rand() % 10 + 10) * U_SECOND; //随机生成思考时间}}else if(state[num] == THINKING){17/ 18//思考一定时间后,哲学家饿了,需要吃饭if(clock() - start_thinking_time[num] >= thinking_time[num]){state[num] = HUNGRY;printf("state: %d %d %d %d %d\n",state[0],state[1],state[2],state[3],state[4]);// printf("%d is hungry\n",num);}}pthread_mutex_unlock(&mutex);}}四、实验小结生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。

linux多线程实验报告

linux多线程实验报告

1实验八 Linux 多线程实验报告撰写人专业班级学号 姓名 完成时间。

一、 实验目的1、 了解什么是多线程,熟悉LINUX 的多线程机制;2、 掌握利用信号处理Linux 多线程的同步问题; 3、 掌握利用信号量处理Linux 多线程的互斥问题;4、 运用Linux 多线程的同步机制和互斥机制实现生产者消费者的编程。

二、 实验内容1. “生产者-消费者”问题如下:有一个有限缓冲区和两个线程:生产者和消费者。

他们分别不停地把产品放入缓冲区、从缓冲区中拿走产品。

一个生产者在缓冲区满的时候必须等待,一个消费者在缓冲区空的时候也必须等待。

另外,因为缓冲区是临界资源,所以生产者和消费者之间必须互斥执行。

它们之间的关系如图1所示。

现在要求使用共享内存来模拟有限缓冲区,并且使用信号量来解决“生产者-消费者”问题中的同步和互斥问题。

生产者和消费者问题描述2. 问题描述:假设有五位哲学家围坐在一张圆形餐桌旁,做以下两件事情之一:吃饭,或者思考。

吃东西的时候,他们就停止思考,思考的时候也停止吃东西。

餐桌中间有一大碗意大利面,每两个哲学家之间有一只餐叉。

因为用一只餐叉很难吃到意大利面,所以假设哲学家必须用两只餐叉吃东西。

他们只能使用自己左右手边的那两只餐叉。

请用Linux 线程编程解决。

2 哲学家进餐问题示意图三、实验过程与结果操作过程错误解决方法实验步骤一:编写的文件在不同的编译21器中for循环的用法不太一样,在这里最好不要使用for(inti=0;;)最好在外声明int i在for循环里直接写i=0步骤二:编译代码并且运行代码步骤三:运行完毕后,显示以下代码:生产者消费者先后生产数据以及取出数据,此程序中设置了两个消费者两个生产者,交替进行生产数据消费数据。

3实验步骤一:编写的文件42步骤二:编译代码并且运行代码步骤三:5实验代码实验一:#include <>#include <>#include <>#include <>#include <sys/>#include <sys/>#include <sys/>#include <sys/>#define MAX_BUFFER_SIZE 106#define SHM_MODE 0600#define SEM_MODE 0600#define SEM_FULL 0#define SEM_EMPTY 1#define MUTEX 2/*#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)\n", i + 1, c);printf("-------------------------------------------------------------\ n");fflush(stdout);sigSem(sem_id, MUTEX);sigSem(sem_id, SEM_FULL);}\n", i + 1, lt);printf("-------------------------------------------------------------\ n");fflush(stdout);sigSem(sem_id,MUTEX);sigSem(sem_id,SEM_EMPTY);}//将共享段与进程之间解除连接shmdt(shmptr);exit(0);}}//主进程最后退出7while (wait(0) != -1);//将共享段与进程之间解除连接shmdt(shmptr);//对共享内存区执行控制操作shmctl(shm_id,IPC_RMID,0);//当cmd为IPC_RMID时,删除该共享段shmctl(sem_id,IPC_RMID,0);printf("主进程运行结束!\n");fflush(stdout);exit(0);return 0;}实验二:#include<sys/>#include<>#include<>#include<>#include<>#include<>#include<>#define N 5 //哲学家数量#define LEFT(i) (i+N-1)%N //左手边哲学家编号#define RIGHT(i) (i+1)%N //右手边哲家编号#define HUNGRY 0 //饥饿#define THINKING 1 //思考#define EATING 2 //吃饭8#define U_SECOND 1000000 //1秒对应的微秒数pthread_mutex_t mutex; //互斥量int state[N]; //记录每个哲学家状态//每个哲学家的思考时间,吃饭时间,思考开始时间,吃饭开始时间clock_t thinking_time[N], eating_time[N], start_eating_time[N], start_thinking_time[N];//线程函数void *thread_function(void *arg);int main(){pthread_mutex_init(&mutex, NULL);pthread_t a,b,c,d,e;//为每一个哲学家开启一个线程,传递哲学家编号pthread_create(&a,NULL,thread_function,"0");pthread_create(&b,NULL,thread_function,"1");pthread_create(&c,NULL,thread_function,"2");pthread_create(&d,NULL,thread_function,"3");pthread_create(&e,NULL,thread_function,"4");//初始化随机数种子srand((unsigned int)(time(NULL)));while(1){;}}9void *thread_function(void *arg){char *a = (char *)arg;int num = a[0] - '0'; //根据传递参数获取哲学家编号int rand_time;while(1){//关键代码加锁pthread_mutex_lock(&mutex);//如果该哲学家处于饥饿并且左右两位哲学家都没有在吃饭就拿起叉子吃饭if(state[num] == HUNGRY && state[LEFT(num)] != EATING && state[RIGHT(num)] != EATING){state[num] = EATING;start_eating_time[num] = clock(); //记录开始吃饭时间eating_time[num] = (rand() % 5 + 5) * U_SECOND; //随机生成吃饭时间//输出状态printf("state: %d %d %d %d %d\n",state[0],state[1],state[2],state[3],stat e[4]);//printf("%d is eating\n",num);}else if(state[num] == EATING){//吃饭时间已到,开始思考if(clock() - start_eating_time[num] >= eating_time[num]) //10{state[num] = THINKING;//printf("%d is thinking\n",num);printf("state: %d %d %d %d %d\n",state[0],state[1],state[2],state[3],stat e[4]);start_thinking_time[num] = clock(); //记录开始思考时间thinking_time[num] = (rand() % 10 + 10) * U_SECOND; //随机生成思考时间}}else if(state[num] == THINKING){//思考一定时间后,哲学家饿了,需要吃饭if(clock() - start_thinking_time[num] >= thinking_time[num]){state[num] = HUNGRY;printf("state: %d %d %d %d %d\n",state[0],state[1],state[2],state[3],stat e[4]);// printf("%d is hungry\n",num);}}pthread_mutex_unlock(&mutex);}}11四、实验小结生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。

linux操作系统-实验-Linux-多线程编程

linux操作系统-实验-Linux-多线程编程

《操作系统》实验报告用gcc编译的时候需要加-lpthread,否则会出现以下错误:五、思考题多进程编程与多线程编程有何区别?相同点:Linux下不管是多线程编程还是多进程编程,最终都是用do_fork 实现不同点:父子进程变量是互不影响的,由于父子进程地址空间是完全隔开的,变量的地址可以是完全相同的。

Linux下编程多用多进程编程少用多线程编程。

多线程比多进程成本低,但性能更低:多进程是立体交通系统,虽然造价高,上坡下坡多耗点油,但是不;多线程是平面交通系统,造价低,但红绿灯太多,老堵车。

1、多进程:子进程是父进程的复制品。

子进程获得父进程数据空间、堆和栈的复制品。

2、多线程:相对与进程而言,线程是一个更加接近与执行体的概念,它可以与同进程的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。

两者都可以提高程序的并发度,提高程序运行效率和响应时间。

3、线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源管理和保护;而进程正相反。

同时,线程适合于在5MP机器上运行,而进程则可以跨机器迁移。

代码:#include <pthread.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>char globe_buffer[100];void *read_buffer_thread(void *arg);int main(){int res,i;pthread_t read_thread;for(i=0;i<20;i++)globe_buffer[i]=i;printf("\nxiancheng thread : write buffer finish\n");sleep(3);res = pthread_create(&read_thread, NULL, read_buffer_thread, NULL);if (res != 0){printf("Read Thread creat Error!");exit(0);}sleep(1);printf("waiting for read thread to finish...\n");res = pthread_join(read_thread, NULL);if (res != 0){printf("read thread join failed!\n");exit(0);}printf("read thread xiancheng OK, have fun!! exit ByeBye\n");return 0;}void *read_buffer_thread(void *arg){int i,x;printf("Read buffer thread read data : \n");for(i=0;i<20;i++){x=globe_buffer[i];printf("%d ",x);globe_buffer[i]=0;}printf("\nread over\n");}。

读者写者问题实验报告3

读者写者问题实验报告3

课程设计题目实现读者写者(Reader-Writer Problem) 问题学院计算机科学与技术专业软件工程班级软件0704姓名万力指导教师刘军2010 年 6 月27 日目录1.概述 (4)1.1设计题目 (4)1.2设计目的 (4)1.3设计时间 (4)1.4开发环境 (4)1.5设计要求 (4)2.数据结构与模块说明 (5)2.1设计概述 (5)2.2设计流程图 (6)3.具体编程实现 (7)4.运行结果与测试 (8)5. 课程设计总结与体会 (11)6.参考文献 (11)课程设计任务书学生姓名:万力专业班级:软件0704 指导教师:刘军工作单位:计算机科学与技术学院题目: 实现读者写者 (Reader-Writer Problem) 问题初始条件:1.操作系统:Linux2.程序设计语言:C语言3.设有20个连续的存储单元,写入/读出的数据项按增序设定为1-20这20个字符。

要求完成的主要任务:(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)1.技术要求:1)为每个读者/写者产生一个线程,设计正确的同步算法2)每个读者/写者对该存储区进行操作后,即时显示该存储区的全部内容、当前指针位置和读者/写者线程的自定义标识符。

3)读者应有3个以上,写者应有有两个以上。

4)多个读者/写者之间须共享对存储区进行操作的函数代码。

2.设计说明书内容要求:1)设计题目与要求2)总的设计思想及系统平台、语言、工具等。

3)数据结构与模块说明(功能与流程图)4)运行结果与运行情况(提示: (1)连续存储区可用数组实现。

(2)编译命令可用:cc -lpthread -o 目标文件名源文件名(3)多线程编程方法参见附件。

)3. 调试报告:1) 调试记录2)自我评析和总结上机时间安排:18周一~ 五08:0 -12:00指导教师签名:年月日系主任(或责任教师)签名:年月日实现读者写者(Reader-Writer Problem) 问题1 概述1.1 设计题目实现读者写者 (Reader-Writer Problem) 问题1.2设计目的通过对操作系统内核实现代码的阅读、修改、设计,理解和掌握复杂的操作系统的工作原理。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

计算机科学与技术系
实验(项目)报告
一、基本信息
二、目的与要求
目的:
通过实验掌握Linux环境下多线程程序的开发方法。

要求:
1.掌握线程的基本概念及操作;
2.掌握线程间通信的基本方法;
3.掌握Linux环境下多线程程序的开发方法及步骤。

三、完成实验(项目)过程和效果
内容:
1.问题分析;
有100个读线程和100个写线程共同读、写文件
(1)允许多个reader同时读一个文件;
(2)当有一个reader在读文件时,不允许writer写文件;
(3)当有一个writer在写文件时,不允许reader读文件,也不允许其
他writer写文件。

2.程序实现;
3.程序的调试与运行。

步骤:
1.问题分析
可以利用读写锁解决读者-写者问题
2.程序实现
1)读者:
void *Reader(void *id)
{
RandomSleep();
pthread_rwlock_rdlock(&rwlock);
ReaderNum++;
ReadFile(*((int *)id));
ReaderNum--;
pthread_rwlock_unlock(&rwlock); }
2)写者:
void *Writer(void *id)
{
RandomSleep();
pthread_rwlock_wrlock(&rwlock);
WriterNum++;
WriteFile(*((int *)id));
WriterNum--;
pthread_rwlock_unlock(&rwlock);
}
3)线程的创建:
for(i=0; i<NUM; i++)
{
id[i] = i;
pthread_create(&readthread[i], NULL, Reader, (void *)&id[i]);
pthread_create(&writethread[i], NULL, Writer, (void *)&id[i]);
}
for(i=0; i<NUM; i++)
{
pthread_join(readthread[i], NULL);
pthread_join(writethread[i], NULL);
}
3.程序的调试与运行
四、知识应用以及经验总结
1.线程与进程的区别?
(1)一个程序至少有一个进程,一个进程至少有一个线程。

(2)线程的划分尺度小于进程,使得多线程程序的并发性高。

(3)进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。

线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源的管理和保护;进程正相反。

一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行。

相关文档
最新文档