读者优先描述
如果读者来:
1) 无读者、写着,新读者可以读;
2) 无写者等待,但有其他读者正在读,新读者可以读;
3) 有写者等待,但有其他读者正在读,新读者可以读;
4) 有写者写,新读者等
如果写者来:
1) 无读者,新写者可以写;
2) 有读者,新写者等待;
3) 有其他写者写或等待,新写者等待
写者优先描述
如果读者来:
1) 无读者、写者,新读者可以读;
2) 无写者等待,但有其他读者正在读,新读者可以读;
3) 有写者等待,但有其他读者正在读,新读者等;
4) 有写者写,新读者等
如果写者来:
1) 无读者,新写者可以写;
2) 有读者,新写者等待;
3) 有其他写者或等待,新写者等待
信号量和互斥锁的区别
l 互斥量用于线程的互斥,信号量用于线程的同步。
这是互斥量和信号量的根本区别,也就是互斥和同步之间的区别。
互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。
同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源
l 互斥量值只能为0/1,信号量值可以为非负整数。
也就是说,一个互斥量只能用于一个资源的互斥访问,它不能实现多个资源的多线程互斥问题。信号量可以实现多个同类资源的多线程互斥和同步。当信号量为单值信号量是,也可以完成一个资源的互斥访问。
l 互斥量的加锁和解锁必须由同一线程分别对应使用,信号量可以由一个线程释放,另一个线程得到。
读者优先
使用互斥锁来确保同一时间只能一个进程写文件,实现互斥。使用信号量来实现访问资源的同步。
首先,写者的代码应该是这样一种形式,才能保证同一时刻只有一个写者修改数据。
考虑到写者对读者的影响是:当任何读者想读时,写者都必须被阻塞;并且,读者阻塞了写者并停止阻塞之前,后续的任何写者都会读者优先于执行。这就如同有一个读者队列,当第一个读者入队时,写者完全被阻塞,直到最后一个读者离开队列。
据此,可以用 readerCnt来统计读者的数量,而用信号量 sem_read来互斥各线程对 readerCnt的访问。
1 /* 2 * 多线程,读者优先 3 */ 4 5 #include "stdio.h" 6 #include <stdlib.h> 7 #include <pthread.h> 8 #include<semaphore.h> 9 10 11 #define N_WRITER 30 //写者数目 12 #define N_READER 5 //读者数目 13 #define W_SLEEP 1 //控制写频率 14 #define R_SLEEP 1 //控制读频率 15 16 17 pthread_t wid[N_WRITER],rid[N_READER]; 18 pthread_mutex_t mutex_write;//同一时间只能一个人写文件,互斥 19 sem_t sem_read;//同一时间只能有一个人访问 readerCnt 20 int data = 0; 21 int readerCnt = 0; 22 void write() 23 { 24 int rd = rand(); 25 printf("write %d\n",rd); 26 data = rd; 27 } 28 void read() 29 { 30 printf("read %d\n",data); 31 } 32 void * writer(void * in) 33 { 34 // while(1) 35 // { 36 pthread_mutex_lock(&mutex_write); 37 printf("写线程id%d进入数据集\n",pthread_self()); 38 write(); 39 printf("写线程id%d退出数据集\n",pthread_self()); 40 pthread_mutex_unlock(&mutex_write); 41 sleep(W_SLEEP); 42 // } 43 pthread_exit((void *) 0); 44 } 45 46 void * reader (void * in) 47 { 48 // while(1) 49 // { 50 sem_wait(&sem_read); 51 readerCnt++; 52 if(readerCnt == 1){ 53 pthread_mutex_lock(&mutex_write); 54 } 55 sem_post(&sem_read); 56 printf("读线程id%d进入数据集\n",pthread_self()); 57 read(); 58 printf("读线程id%d退出数据集\n",pthread_self()); 59 sem_wait(&sem_read); 60 readerCnt--; 61 if(readerCnt == 0){ 62 pthread_mutex_unlock(&mutex_write); 63 } 64 sem_post(&sem_read); 65 sleep(R_SLEEP); 66 // } 67 pthread_exit((void *) 0); 68 } 69 70 int main() 71 { 72 printf("多线程,读者优先\n"); 73 pthread_mutex_init(&mutex_write,NULL); 74 sem_init(&sem_read,0,1); 75 int i = 0; 76 for(i = 0; i < N_WRITER; i++) 77 { 78 pthread_create(&wid[i],NULL,writer,NULL); 79 } 80 for(i = 0; i < N_READER; i++) 81 { 82 pthread_create(&rid[i],NULL,reader,NULL); 83 } 84 sleep(1); 85 return 0; 86 }