信號量和互斥鎖的區(qū)別
互斥量用于線程的互斥,信號量用于線程的同步。
這是互斥量和信號量的根本區(qū)別,也就是互斥和同步之間的區(qū)別。
互斥:是指某一資源同時(shí)只允許一個(gè)訪問者對其進(jìn)行訪問,具有唯一性和排它性。但互斥無法限制訪問者對資源的訪問順序,即訪問是無序的。
同步:是指在互斥的基礎(chǔ)上(大多數(shù)情況),通過其它機(jī)制實(shí)現(xiàn)訪問者對資源的有序訪問。在大多數(shù)情況下,同步已經(jīng)實(shí)現(xiàn)了互斥,特別是所有寫入資源的情況必定是互斥的。少數(shù)情況是指可以允許多個(gè)訪問者同時(shí)訪問資源
互斥量值只能為0/1,信號量值可以為非負(fù)整數(shù)。
也就是說,一個(gè)互斥量只能用于一個(gè)資源的互斥訪問,它不能實(shí)現(xiàn)多個(gè)資源的多線程互斥問題。信號量可以實(shí)現(xiàn)多個(gè)同類資源的多線程互斥和同步。當(dāng)信號量為單值信號量是,也可以完成一個(gè)資源的互斥訪問。
互斥量的加鎖和解鎖必須由同一線程分別對應(yīng)使用,信號量可以由一個(gè)線程釋放,另一個(gè)線程得到。
讀者優(yōu)先
使用互斥鎖來確保同一時(shí)間只能一個(gè)進(jìn)程寫文件,實(shí)現(xiàn)互斥。使用信號量來實(shí)現(xiàn)訪問資源的同步。
首先,寫者的代碼應(yīng)該是這樣一種形式,才能保證同一時(shí)刻只有一個(gè)寫者修改數(shù)據(jù)。
考慮到寫者對讀者的影響是:當(dāng)任何讀者想讀時(shí),寫者都必須被阻塞;并且,讀者阻塞了寫者并停止阻塞之前,后續(xù)的任何寫者都會讀者優(yōu)先于執(zhí)行。這就如同有一個(gè)讀者隊(duì)列,當(dāng)?shù)谝粋€(gè)讀者入隊(duì)時(shí),寫者完全被阻塞,直到最后一個(gè)讀者離開隊(duì)列。
據(jù)此,可以用 readerCnt來統(tǒng)計(jì)讀者的數(shù)量,而用信號量 sem_read來互斥各線程對 readerCnt的訪問。
/*
* 多線程,讀者優(yōu)先
*/
#include “stdio.h”
#include
#include
#include
#define N_WRITER 30 //寫者數(shù)目
#define N_READER 5 //讀者數(shù)目
#define W_SLEEP 1 //控制寫頻率
#define R_SLEEP 1 //控制讀頻率
pthread_t wid[N_WRITER],rid[N_READER];
pthread_mutex_t mutex_write;//同一時(shí)間只能一個(gè)人寫文件,互斥
sem_t sem_read;//同一時(shí)間只能有一個(gè)人訪問 readerCnt
int data = 0;
int readerCnt = 0;
void write()
{
int rd = rand();
printf(“write %d\n”,rd);
data = rd;
}
void read()
{
printf(“read %d\n”,data);
}
void * writer(void * in)
{
// while(1)
// {
pthread_mutex_lock(&mutex_write);
printf(“寫線程id%d進(jìn)入數(shù)據(jù)集\n”,pthread_self());
write();
printf(“寫線程id%d退出數(shù)據(jù)集\n”,pthread_self());
pthread_mutex_unlock(&mutex_write);
sleep(W_SLEEP);
// }
pthread_exit((void *) 0);
}
void * reader (void * in)
{
// while(1)
// {
sem_wait(&sem_read);
readerCnt++;
if(readerCnt == 1){
pthread_mutex_lock(&mutex_write);
}
sem_post(&sem_read);
printf(“讀線程id%d進(jìn)入數(shù)據(jù)集\n”,pthread_self());
read();
printf(“讀線程id%d退出數(shù)據(jù)集\n”,pthread_self());
sem_wait(&sem_read);
readerCnt--;
if(readerCnt == 0){
pthread_mutex_unlock(&mutex_write);
}
sem_post(&sem_read);
sleep(R_SLEEP);
// }
pthread_exit((void *) 0);
}
int main()
{
printf(“多線程,讀者優(yōu)先\n”);
pthread_mutex_init(&mutex_write,NULL);
sem_init(&sem_read,0,1);
int i = 0;
for(i = 0; i 《 N_WRITER; i++)
{
pthread_create(&wid[i],NULL,writer,NULL);
}
for(i = 0; i 《 N_READER; i++)
{
pthread_create(&rid[i],NULL,reader,NULL);
}
sleep(1);
return 0;
}
讀者優(yōu)先
為了更明顯的看到效果,在main函數(shù)中創(chuàng)建了20個(gè)寫者和5個(gè)讀者。注意編譯時(shí)要加上-lpthread指定庫。
寫者優(yōu)先
寫者優(yōu)先與讀者優(yōu)先的不同是:如果讀者來,有寫者等待,但有其他讀者正在讀,新讀者等。
使用兩個(gè)互斥鎖mutex_write,mutex_read和兩個(gè)信號量sem_read,sem_write來確保訪問資源的互斥和同步。
#include “stdio.h”
#include
#include
#include
#define N_WRITER 5 //寫者數(shù)目
#define N_READER 20 //讀者數(shù)目
#define W_SLEEP 1 //控制寫頻率
#define R_SLEEP 0.5 //控制讀頻率
pthread_t wid[N_WRITER],rid[N_READER];
int data = 0;
int readerCnt = 0, writerCnt = 0;
pthread_mutex_t sem_read;
pthread_mutex_t sem_write;
pthread_mutex_t mutex_write;
pthread_mutex_t mutex_read;
void write()
{
int rd = rand();
printf(“write %d\n”,rd);
data = rd;
}
void read()
{
printf(“read %d\n”,data);
}
void * writer(void * in)
{
// while(1)
// {
sem_wait(&sem_write);
{//臨界區(qū),希望修改 writerCnt,獨(dú)占 writerCnt
writerCnt++;
if(writerCnt == 1){
//阻止后續(xù)的讀者加入待讀隊(duì)列
pthread_mutex_lock(&mutex_read);
}
}
sem_post(&sem_write);
pthread_mutex_lock(&mutex_write);
{//臨界區(qū),限制只有一個(gè)寫者修改數(shù)據(jù)
printf(“寫線程id%d進(jìn)入數(shù)據(jù)集\n”,pthread_self());
write();
printf(“寫線程id%d退出數(shù)據(jù)集\n”,pthread_self());
}
pthread_mutex_unlock(&mutex_write);
sem_wait(&sem_write);
{//臨界區(qū),希望修改 writerCnt,獨(dú)占 writerCnt
writerCnt--;
if(writerCnt == 0){
//阻止后續(xù)的讀者加入待讀隊(duì)列
pthread_mutex_unlock(&mutex_read);
}
}
sem_post(&sem_write);
sleep(W_SLEEP);
// }
pthread_exit((void *) 0);
}
void * reader (void * in)
{
// while(1)
// {
//假如寫者鎖定了mutex_read,那么成千上萬的讀者被鎖在這里
pthread_mutex_lock(&mutex_read);//只被一個(gè)讀者占有
{//臨界區(qū)
sem_wait(&sem_read);//代碼段 1
{//臨界區(qū)
readerCnt++;
if(readerCnt == 1){
pthread_mutex_lock(&mutex_write);
}
}
sem_post(&sem_read);
}
pthread_mutex_unlock(&mutex_read);//釋放時(shí),寫者將優(yōu)先獲得mutex_read
printf(“讀線程id%d進(jìn)入數(shù)據(jù)集\n”,pthread_self());
read();
printf(“讀線程id%d退出數(shù)據(jù)集\n”,pthread_self());
sem_wait(&sem_read);//代碼段2
{//臨界區(qū)
readerCnt--;
if(readerCnt == 0){
pthread_mutex_unlock(&mutex_write);//在最后一個(gè)并發(fā)讀者讀完這里開始禁止寫者執(zhí)行寫操作
}
}
sem_post(&sem_read);
sleep(R_SLEEP);
// }
pthread_exit((void *) 0);
}
int main()
{
printf(“多線程,寫者優(yōu)先\n”);
pthread_mutex_init(&mutex_write,NULL);
pthread_mutex_init(&mutex_read,NULL);
sem_init(&sem_write,0,1);
sem_init(&sem_read,0,1);
int i = 0;
for(i = 0; i 《 N_READER; i++)
{
pthread_create(&rid[i],NULL,reader,NULL);
}
for(i = 0; i 《 N_WRITER; i++)
{
pthread_create(&wid[i],NULL,writer,NULL);
}
sleep(1);
return 0;
}
寫者優(yōu)先
評論
查看更多