linuxpv操作
❶ 急求关于操作系统PV操作的程序代码C或C++都可以,在线等啊!!!!!!!!!!
完整程序要花不少时间调试的,我这里给你一个实现PV操作的程序吧,5个人抢3个位子,这个你们上课应该会讲的,通过几个pv操作就可以实现,只要把我这里写的pv操作的代码用上就可以了。程序是在linux系统下调试的。pv操作分别对应下面的up和down(我们老师习惯用这种称呼,于是就在代茄悉拦码中也这么用了)
#include <stdio.h>#include <signal.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/mman.h>#include <sys/times.h>#include <fcntl.h>#include <stdlib.h>#include <sys/sem.h> //include header file for semaphore #define FILE_SIZE 11#define NO_PROC 10 int DelayCount = 0; int readerID = 0;int writerID = 0; char* shared_buffer; int Delay100ms = 0; int* shared_buffer2;////////Variables for semaphoreoperations//陆隐///int semid;// the followings are not necessary to definehere, but just for conveniencekey_t semkey;struct sembuf operation[1];short sarray[2];int ret_val;/////////////////////////颤胡////////////////////// void init_sem(){ int*rc; //getkey semkey=ftok("/dev/null",12); if( semkey == (key_t) -1 ) { printf("main:ftok() failed\n"); exit(-1); } printf("semkeygenerated\n"); //getsemaphore set semid= semget( semkey, 2, 0666 | IPC_CREAT | IPC_EXCL ); if( semid == -1 ) { printf("main: semget()failed\n"); exit(-1); } //setthe two semaphores to 1; sarray[0]=1; sarray[1]=1; ret_val=semctl(semid,1, SETALL, sarray); if(ret_val==-1) { printf("main:semctlerror\n"); exit(-1); } printf("ddddd\n"); //setreader count rc=(int*)(&shared_buffer[FILE_SIZE]); //printf("%d\n",*shared_buffer2); *rc=0; printf("RC:%d\n",*rc);} void down(int i) //i=0, 1{ operation[0].sem_num=i; operation[0].sem_op=-1; operation[0].sem_flg=0; ret_val=semop(semid,operation,1);} void up(int i){ operation[0].sem_num=i; operation[0].sem_op=1; operation[0].sem_flg=0; ret_val=semop(semid,operation,1);}
❷ linux下创建新的PV 不能创建
如果你要将一个分区初始化成搜首尘PV,你必须首先保证这个分区没有被使用,也就是处在离线状态,你可以先umount /dev/sda先把这个分区卸下来然后再做PV操作芹碰。如果sda挂在你世禅的根分区下,那么很不好意思,你已经无法将它初始化成PV了。。。。。
❸ linux 下运行C的程序,终端运行出现乱码,该怎么解决!!
在linux下,其实不用选择gb2312,我都用的是utf8,当然也需要按照以上步骤进行设陆胡念置,肯定不会出现乱码!个人喜好,大家随意!
之前我试了很多方法,比如在/etc/sysconfig/i18n文件中改系统字体,在/etc/my.cnf中[mysqld]字段后加入如下语句default-character-set=gb2312等等早困,我觉得没有必要。
以上步骤看似很简单,但是我的失败教训,也是我的成功心得。现在与大家分享,看后有收获的做慎,不顶一下就是你的不厚道了!
❹ linux中什么是ptlib
ptlib 就是指pwlib
PWLib是Portable Windows
Library的缩写,翻译为轻便的Windows类库.PWLib采用C++编写,设计初衷是为了能让Openh323在Windows和Unix的
X-Windows下运行,
不过随着一步步的完善PWLib已经被跨平台的程序所广泛采用.在最新的Pandora版本中,Equivalence已经停止了PWLib中GUI部分
的开发,全面转向了更能为Openh323所利用的PTLib,GUI部分交给了wxWindows来完成.PWLib主要功能侧向网络,I/O和多线
程,主要用在高性能的可移植网络程序.
PWLib分为两部分:基类部分和控制台部分.基类部分主要包括网络,多线程,ASN等...,所有使用PWLib的应用程序必然用到基类部分.而控制台部分则定义了一些基本的数据和设备类型,它是可选的,不过要方便移植的话还是要用到它.
下面从Hello World开始说PWLib框架:
#include //所用使用PWLib都用包含的知庆头文件
class Hello : public PProcess //继承主线程类PProcess
{
PCLASSINFO(Hello, PProcess) //连接PProcess的运行时函数
public:
void Main(); //主线程是从PProcess的Main()开始的
};
PCREATE_PROCESS(Hello) //定义Main()函数和初始化Hello类
void Hello::Main()
{
cout << "Hello world!\n";
}
下面详细介绍各个类:
基本对象类:
PObject - PWLib中的根类,所有的类都派生于此
PContainer - 抽象容器类
PAbstractArray - 所有数组对象的基类
PAbstractList - 所有列表对象的基类
PAbstractDictionary - 字典对象的基类
PString - 字符类,在Openh323中随处可见
I/O通道类
PChannel - I/O通道的基类,下面类都派生于此
PIndirectChannel - 可以交换的操作不同的I/O通道
PConsoleChannel - 进入系统命令行的通道
PPipeChannel - 在当前进程和子进程剪建立管道
PSerialChannel - 串口通信通道
PFile - 文件操作类.
PTextFile - 文本文件操作类
PStructuredFile - 结构文件操作类,不同操作文件类型都不尽相同
PFilePath -对文件的路径描述的类
PVideoChannel - 视频的输入,输出通道,采用YUV格式
PSoundChannel - 音频的输入,输出通孙渣道,使用线性的PCM通道
套接字类:
PSocket - 套接字的基类,所有网络操作类派生于此
PIPSocket - IP协议层的描述类
PUDPSocket - IP协议中UDP描述类
PTCPSocket - IP协议中TCP/IP描述类
PICMPSocket - IP协议中ICMP描述类
PIPXSocket - IPX协议的基类
PEthSocket - 底层的以为网接口类,可以直接操作底层数据包
进程和线程类:
PProcess - 实现程序的主线程控制类
PServiceProcess - 后台程序或系统进程使用的类
PThread - 普通线程的控制类
PSemaphore - 使用搭凯握信号量的线程同步类
PMutex - 使用互斥对象的线程同步类
PCriticalSection - 使用临界区的线程同步类
PSyncPoint - 使用事件的线程同步类
PAtomicInteger - 描述了信号量及PV操作
其他杂类:
PArgList - 命令行参数类
PConfig - 存储应用程序的配置内容
PTime - 时间和日期的抽象类
PTimeInterval - 以毫秒为单位的记时类
PDynaLink - 动态连接类
PRemoteConnection - 网络连接控制类
PMail - 调用系统默认程序发邮件
PPluginManager - 插件管理模块
PSmartPointer - 智能指令类
PNotifier - 通告类,可以调用任何类的任何函数
PSmartNotifierFunction - 智能的通告函数类,使用对象ID
控制台部分:
HTTP协议类:
PHTTP - HTTP协议基类
PURL - URL的具体描述
PHTML - HTML的具体描述
PHTTPServiceProcess - 后台的HTTP服务程序类
其他协议类
PInternetProtocol - Interner文本协议基类
PPOP3 - POP3协议的基类
PSMTMP - SMTP协议的基类
PFTP - FTP协议的基类
PMIMEInfo - 描述MIME信息
PTelnetSocket - 描述TELNET协议
PSocksProtocol - Socks协议的基类
PSTUNClient - 实现STUN登陆操作
PSNMP - SNMP协议的基类
PSSLChannel - 在OpenSSL基础上建立的SSL协议类
PSASL - 在Cyrus SASL基础上建立的SAS协议L类
PXMLRPC - 在XML和HTTP基础上建立的XMLRPC协议描述
PSOAPClient - 实现SOAP登陆
PLDAPSession - 使用OpenLDAP进行LDAP登陆
PILSSession - 使用OpenLDAP进行ILS登陆
XMPP::Stream - 实现XMPP(Jabber)流
其他杂类:
PModem -操作Modem,使用AT命令和Modem串口通信
PIpAccessControlList - 子网掩码的描述
PRandom - 产生随机数类
PCypher - 不同编码的解码和编码
PWAVFile - AIFF格式的WAV文件操作类
PDTMFDecoder - 对PCM流进行DTMF解码
PMemoryFile - 让数据存储在内存中
PSDLVideoDevice - 使用SDL库实现视频设备
PXML - XML的解析器
PVXMLChannel - VXML的解析器
PTextToSpeech - 实现文本到语音的语音合成转换
❺ LINUX 信号量共存 共享内存通信
/***Msginput.c***/
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/sem.h>
#include<unistd.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#include"Mysem.h"
int main(){
FILE *fp;
int empty;
int full;
int mutex;
char * shm;
int shmid;
fp = fopen("shmid","r");
fread(&shmid,sizeof(int), 1, fp);
fread(&empty,sizeof(int), 1, fp);
fread(&full,sizeof(int), 1, fp);
fread(&mutex,sizeof(int), 1, fp);
fclose(fp);
shm = shmat(shmid, NULL, 0);
while(1){
P(&empty);
P(&mutex);
scanf("%s", shm);
if(strcmp(shm, "END") == 0){
V(&mutex);
V(&full);
break;
}
V(&mutex);
V(&full);
}
return 0;
}
/****Mysem.c*****/
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/sem.h>
#include<unistd.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#include "Mysem.h"
#define BUFFER_SIZE 512
int main(){
char *shm;
int empty;
int full;
int mutex;
int shmid;
int pid;
int i;
FILE *fp;
// int init_sem_value = 0;
empty = semget(IPC_PRIVATE, 1, (0600|IPC_CREAT));
if(empty == -1){
perror("semget");
exit(1);
}
if(semctl(empty, 0, SETVAL, 1)<0){
perror("semctl");
exit(1);
}
full = semget(IPC_PRIVATE, 1, (0600|IPC_CREAT));
if(full == -1){
perror("semget");
exit(1);
}
if(semctl(full, 0, SETVAL, 0)<0){
perror("semctl");
exit(1);
}
mutex = semget(IPC_PRIVATE, 1, (0600|IPC_CREAT));
if(mutex == -1){
perror("semget");
exit(1);
}
if(semctl(mutex, 0, SETVAL, 1)<0){
perror("semctl");
exit(1);
}
shmid = shmget(IPC_PRIVATE, (BUFFER_SIZE*sizeof(char)),(IPC_CREAT|0600));
if(shmid == -1){
perror("shmget");
exit(1);
}
shm = shmat(shmid, NULL, 0);
if(shm == (char*)-1){
perror("shmat");
exit(1);
}
fp = fopen("shmid","w");
fwrite(&shmid, sizeof(int), 1, fp);
fwrite(&empty, sizeof(int), 1, fp);
fwrite(&full, sizeof(int), 1, fp);
fwrite(&mutex, sizeof(int), 1, fp);
fclose(fp);
pid = fork();
if(pid == 0){
execlp("./Msginput", "./Msginput",0);
perror("execlp");
exit(1);
}else{
while(1){
P(&full);
P(&mutex);
printf("%s\n", shm);
if(strcmp(shm,"END") == 0){
V(&mutex);
V(&empty);
break;
}
V(&mutex);
V(&empty);
}
}
wait(0);
if(semctl(full, 0, IPC_RMID, 1) == -1){
perror("semctl");
exit(1);
}
if(semctl(empty, 0, IPC_RMID, 1) == -1){
perror("semctl");
exit(1);
}
if(semctl(mutex, 0, IPC_RMID, 1) == -1){
perror("semctl");
exit(1);
}
if(shmctl(shmid, IPC_RMID, NULL) == -1){
perror("shmctl");
exit(1);
}
exit(0);
}
/****Mysem.h*****/
void P(int *s);
void V(int *s);
extern void *shmat (int __shmid, __const void *__shmaddr, int __shmflg);
void P(int *s){
struct sembuf sembuffer, *sops;
sops=&sembuffer;
sops->sem_num = 0;
sops->sem_op = -1;
sops->sem_flg = 0;
if(semop(*s, sops, 1)<0){
perror("semop");
exit(1);
}
return ;
}
void V(int *s){
struct sembuf sembuffer, *sops;
sops = &sembuffer;
sops->sem_num = 0;
sops->sem_op = 1;
sops->sem_flg = 0;
if(semop(*s, sops, 1)<0){
perror("semop");
exit(1);
}
return;
}
❻ linux中pv操作伪代码怎么写
//算法描述语言使用基于C语言的伪代码
//算法思想:根据楼主的要求“为防止数的丢失和重复取同一个数”可以看出,进程A、进程B、进程C三者之间应该是互斥的关系。那么问题所限定的使用带埋信号量的方式来管理的潜藏意思,就是要利用PV
原语实现并发进程在资源争夺中拆薯有效互斥。
//而具体实现的目标是“防止数旅行者的丢失”和“重复取同一个数”。由于本人不才,只讨论单任务系统下的状况。
//“数的丢失”的情况主要是进程A产生了随即变量给F后,但在进程B或者进程C处理之前又获得处理机的使用权而覆盖了之前那个未被处理过的F中的数——进程A连续获得处理机的使用权,而进程B、进
❼ LINUX高手进!有关于PV操作的问题!
什么意思?求PV元语具体实现程序?
❽ Linux 多线程编程(二)2019-08-10
三种专门用于线程同步的机制:POSIX信号量,互斥量和条件变量.
在Linux上信号量API有两组,一组是System V IPC信号量,即PV操作,另外就是POSIX信号量,POSIX信号量的名字都是以sem_开头.
phshared参数指定信号量的类型,若其值为0,就表示这个信号量是当前进程的局部信号量,否则该信号量可以在多个进程之间共享.value值指定信号量的初始值,一般与下面的sem_wait函数相对应.
其中比较重要的函数sem_wait函数会以原子操作的方式将信号量的值减一,如果信号量的值为零,则sem_wait将会阻塞,信号量的值可以在sem_init函数中的value初始化;sem_trywait函数是sem_wait的非阻塞版本;sem_post函数将以原子的操作对信号量加一,当信号量的值大于0时,其他正在调用sem_wait等待信号量的线程将被唤醒.
这些函数成功时返回0,失败则返回-1并设置errno.
生产者消费者模型:
生产者对应一个信号量:sem_t procer;
消费者对应一个信号量:sem_t customer;
sem_init(&procer,2)----生产者拥有资源,可以工作;
sem_init(&customer,0)----消费者没有资源,阻塞;
在访问公共资源前对互斥量设置(加锁),确保同一时间只有一个线程访问数据,在访问完成后再释放(解锁)互斥量.
互斥锁的运行方式:串行访问共享资源;
信号量的运行方式:并行访问共享资源;
互斥量用pthread_mutex_t数据类型表示,在使用互斥量之前,必须使用pthread_mutex_init函数对它进行初始化,注意,使用完毕后需调用pthread_mutex_destroy.
pthread_mutex_init用于初始化互斥锁,mutexattr用于指定互斥锁的属性,若为NULL,则表示默认属性。除了用这个函数初始化互斥所外,还可以用如下方式初始化:pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER。
pthread_mutex_destroy用于销毁互斥锁,以释放占用的内核资源,销毁一个已经加锁的互斥锁将导致不可预期的后果。
pthread_mutex_lock以原子操作给一个互斥锁加锁。如果目标互斥锁已经被加锁,则pthread_mutex_lock则被阻塞,直到该互斥锁占有者把它给解锁.
pthread_mutex_trylock和pthread_mutex_lock类似,不过它始终立即返回,而不论被操作的互斥锁是否加锁,是pthread_mutex_lock的非阻塞版本.当目标互斥锁未被加锁时,pthread_mutex_trylock进行加锁操作;否则将返回EBUSY错误码。注意:这里讨论的pthread_mutex_lock和pthread_mutex_trylock是针对普通锁而言的,对于其他类型的锁,这两个加锁函数会有不同的行为.
pthread_mutex_unlock以原子操作方式给一个互斥锁进行解锁操作。如果此时有其他线程正在等待这个互斥锁,则这些线程中的一个将获得它.
三个打印机轮流打印:
输出结果:
如果说互斥锁是用于同步线程对共享数据的访问的话,那么条件变量就是用于在线程之间同步共享数据的值.条件变量提供了一种线程之间通信的机制:当某个共享数据达到某个值时,唤醒等待这个共享数据的线程.
条件变量会在条件不满足的情况下阻塞线程.且条件变量和互斥量一起使用,允许线程以无竞争的方式等待特定的条件发生.
其中pthread_cond_broadcast函数以广播的形式唤醒所有等待目标条件变量的线程,pthread_cond_signal函数用于唤醒一个等待目标条件变量线程.但有时候我们可能需要唤醒一个固定的线程,可以通过间接的方法实现:定义一个能够唯一标识目标线程的全局变量,在唤醒等待条件变量的线程前先设置该变量为目标线程,然后采用广播的方式唤醒所有等待的线程,这些线程被唤醒之后都检查该变量以判断是否是自己.
采用条件变量+互斥锁实现生产者消费者模型:
运行结果:
阻塞队列+生产者消费者
运行结果:
❾ 操作系统的pv操作是编程用的吗百度了很多,请大佬们用通俗的话讲一下,请不要复制粘贴,谢谢。
PV操作是信号量的一种,主要是用在生产者-消费者关系模型里,解决线程/进程并发和资源冲突的问题。在操作系统层面会提供相关的API用于信号量操作,如Windows C和Linux C下都有对应的信号量操作函数。某些编程语言如Java本身也提供信号量等并发机制,它也是依靠操作系统底层的这些API实现的。
❿ 求助,关于linux的线程同步问题
【Linux多线程】三个经典同步问题
标签: 多线程同步生产者与消费者写者与读者
目录(?)[+]
在了解了《同步与互斥的区别 》之后,我们来看看几个经典的线程同步的例子。相信通过具体场景可以让我们学会分析和解决这类线程同步的问题,以便以后应用在实际的项目中。
一、生产者-消费者问题
问题描述:
一组生产者进程和一组消费者进程共享一个初始为空、大小为 n 的缓冲区,只有缓冲区没满时,生产者才能把消息放入到缓冲区,否则必须等待;只有缓冲区不空时,消费者才能从中取出消息,否则必须等待。由于缓冲区是临界资源,它只允许一个生产者放入消息,或者一个消费者从中取出消息。
分析:
关系分析:生产者和消费者对缓冲区互斥访问是互斥关系,同时生产者和消费者又是一个相互协作的关系,只有生产者生产之后,消费者才能消费,它们也是同步关系。
整理思路:这里比较简单,只有生产者和消费者两个进程,且这两个进程存在着互斥关系和同步关系。那么需要解决的是互斥和同步的PV操作的位置。
信号量设置:信号量mutex作为互斥信号量,用于控制互斥访问缓冲池,初值为1;信号量full用于记录当前缓冲池中“满”缓冲区数,初值为 0;信号量empty用于记录当前缓冲池中“空”缓冲区数,初值为n。
代码示例:(semaphore类的封装见下文)
#include<iostream>
#include<unistd.h> // sleep
#include<pthread.h>
#include"semaphore.h"
using namespace std;
#define N 5
semaphore mutex("/", 1); // 临界区互斥信号量
semaphore empty("/home", N); // 记录空缓冲区数,初值为N
semaphore full("/home/songlee",0); // 记录满缓冲区数,初值为0
int buffer[N]; // 缓冲区,大小为N
int i=0;
int j=0;
void* procer(void* arg)
{
empty.P(); // empty减1
mutex.P();
buffer[i] = 10 + rand() % 90;
printf("Procer %d write Buffer[%d]: %d\n",arg,i+1,buffer[i]);
i = (i+1) % N;
mutex.V();
full.V(); // full加1
}
void* consumer(void* arg)
{
full.P(); // full减1
mutex.P();
printf(" \033[1;31m");
printf("Consumer %d read Buffer[%d]: %d\n",arg,j+1,buffer[j]);
printf("\033[0m");
j = (j+1) % N;
mutex.V();
empty.V(); // empty加1
}
int main()
{
pthread_t id[10];
// 开10个生产者线程,10个消费者线程
for(int k=0; k<10; ++k)
pthread_create(&id[k], NULL, procer, (void*)(k+1));
for(int k=0; k<10; ++k)
pthread_create(&id[k], NULL, consumer, (void*)(k+1));
sleep(1);
return 0;
}
编译运行输出结果:
Procer 1 write Buffer[1]: 83
Procer 2 write Buffer[2]: 26
Procer 3 write Buffer[3]: 37
Procer 5 write Buffer[4]: 35
Procer 4 write Buffer[5]: 33
Consumer 1 read Buffer[1]: 83
Procer 6 write Buffer[1]: 35
Consumer 2 read Buffer[2]: 26
Consumer 3 read Buffer[3]: 37
Consumer 4 read Buffer[4]: 35
Consumer 5 read Buffer[5]: 33
Consumer 6 read Buffer[1]: 35
Procer 7 write Buffer[2]: 56
Procer 8 write Buffer[3]: 22
Procer 10 write Buffer[4]: 79
Consumer 9 read Buffer[2]: 56
Consumer 10 read Buffer[3]: 22
Procer 9 write Buffer[5]: 11
Consumer 7 read Buffer[4]: 79
Consumer 8 read Buffer[5]:
二、读者-写者问题
问题描述:
有读者和写者两组并发线程,共享一个文件,当两个或以上的读线程同时访问共享数据时不会产生副作用,但若某个写线程和其他线程(读线程或写线程)同时访问共享数据时则可能导致数据不一致的错误。因此要求:
允许多个读者可以同时对文件执行读操作;
只允许一个写者往文件中写信息;
任一写者在完成写操作之前不允许其他读者或写者工作;
写者执行写操作前,应让已有的读者和写者全部退出。
分析:
关系分析:由题目分析可知,读者和写者是互斥的,写者和写者也是互斥的,而读者和读者不存在互斥问题。
整理思路:写者是比较简单的,它与任何线程互斥,用互斥信号量的 PV 操作即可解决。读者的问题比较复杂,它必须实现与写者的互斥,多个读者还可以同时读。所以,在这里用到了一个计数器,用它来判断当前是否有读者读文件。当有读者的时候写者是无法写文件的,此时读者会一直占用文件,当没有读者的时候写者才可以写文件。同时,不同的读者对计数器的访问也应该是互斥的。
信号量设置:首先设置一个计数器count,用来记录当前的读者数量,初值为0;设置互斥信号量mutex,用于保护更新 count 变量时的互斥;设置互斥信号量rw用于保证读者和写者的互斥访问。
代码示例:
#include<iostream>
#include<unistd.h> // sleep
#include<pthread.h>
#include"semaphore.h"
using namespace std;
int count = 0; // 记录当前的读者数量
semaphore mutex("/",1); // 用于保护更新count变量时的互斥
semaphore rw("/home",1); // 用于保证读者和写者的互斥
void* writer(void* arg)
{
rw.P(); // 互斥访问共享文件
printf(" Writer %d start writing...\n", arg);
sleep(1);
printf(" Writer %d finish writing...\n", arg);
rw.V(); // 释放共享文件
}
void* reader(void* arg)
{
mutex.P(); // 互斥访问count变量
if(count == 0) // 当第一个读线程读文件时
rw.P(); // 阻止写线程写
++count; // 读者计数器加1
mutex.V(); // 释放count变量
printf("Reader %d start reading...\n", arg);
sleep(1);
printf("Reader %d finish reading...\n", arg);
mutex.P(); // 互斥访问count变量
--count; // 读者计数器减1
if(count == 0) // 当最后一个读线程读完文件
rw.V(); // 允许写线程写
mutex.V(); // 释放count变量
}
int main()
{
pthread_t id[8]; // 开6个读线程,2个写线程
pthread_create(&id[0], NULL, reader, (void*)1);
pthread_create(&id[1], NULL, reader, (void*)2);
pthread_create(&id[2], NULL, writer, (void*)1);
pthread_create(&id[3], NULL, writer, (void*)2);
pthread_create(&id[4], NULL, reader, (void*)3);
pthread_create(&id[5], NULL ,reader, (void*)4);
sleep(2);
pthread_create(&id[6], NULL, reader, (void*)5);
pthread_create(&id[7], NULL ,reader, (void*)6);
sleep(4);
return 0;
}555657585960
编译运行的结果如下:
Reader 2 start reading...
Reader 1 start reading...
Reader 3 start reading...
Reader 4 start reading...
Reader 1 finish reading...
Reader 2 finish reading...
Reader 3 finish reading...
Reader 4 finish reading...
Writer 1 start writing...
Writer 1 finish writing...
Writer 2 start writing...
Writer 2 finish writing...
Reader 5 start reading...
Reader 6 start reading...
Reader 5 finish reading...
Reader 6 finish reading...
三、哲学家进餐问题
问题描述:
一张圆桌上坐着 5 名哲学家,桌子上每两个哲学家之间摆了一根筷子,桌子的中间是一碗米饭,如图所示:
哲学家们倾注毕生精力用于思考和进餐,哲学家在思考时,并不影响他人。只有当哲学家饥饿的时候,才试图拿起左、右两根筷子(一根一根拿起)。如果筷子已在他人手上,则需等待。饥饿的哲学家只有同时拿到了两根筷子才可以开始进餐,当进餐完毕后,放下筷子继续思考。
分析:
关系分析:5名哲学家与左右邻居对其中间筷子的访问是互斥关系。
整理思路:显然这里有 5 个线程,那么要如何让一个哲学家拿到左右两个筷子而不造成死锁或饥饿现象?解决方法有两个,一个是让他们同时拿两个筷子;二是对每个哲学家的动作制定规则,避免饥饿或死锁现象的发生。
信号量设置:定义互斥信号量数组chopstick[5] = {1,1,1,1,1}用于对 5 根筷子的互斥访问。
示例代码: