導航:首頁 > 操作系統 > linux讀者寫者問題

linux讀者寫者問題

發布時間:2022-08-10 00:04:17

linux怎麼把文件同時進行讀寫鎖

讀寫鎖與互斥量類似,不過讀寫鎖的並行性更高。
讀寫鎖可以有三種狀態:(1)讀模式加鎖;(2)寫模式加鎖;(3)不加鎖。
在寫加鎖狀態時,在解鎖之前,所有試圖對這個鎖加鎖的線程都會被阻塞。在讀加鎖狀態時,所有試圖以讀模式對它進行加鎖的線程都可以得到訪問許可權。但是如果線程希望以寫模式加鎖,它必須阻塞,直至所有的線程釋放讀鎖。
讀寫鎖很適合於對數據結構讀的次數遠大於寫的情況。

相關函數:
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock) // 成功則返回0,失敗則返回錯誤代碼
int pthread_rwlock_rdlock(pthread_rwlock_t *restrict rwlock) ;//讀模式加鎖
int pthread_rwlock_wrlock(pthread_rwlock_t *restrict rwlock);//寫模式加鎖
int pthread_rwlock_unlock(pthread_rwlock_t *restrick rwlock);
int pthread_rwlock_tryrdlock(pthread_rwlock_t *restrict rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *restrict rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *restrict rwlock);
相關示例:讀者寫者問題,這也是一個很經典的多線程題目,題目大意:有一個寫者多個讀者,多個讀者可以同時讀文件,但寫者在寫文件時不允許有讀者在讀取文件,同樣有讀者讀文件時
#include <stdio.h>
#include <pthread.h>

#define Read_Num 2

pthread_rwlock_t lock;

class Data
{
public:
Data(int i, float f): I(i),F(f)
{}
private:
int I;
float F;

};

Data *pdata = NULL;

void *read(void * arg)
{
int id = (int)arg;
while(true)
{

pthread_rwlock_rdlock(&lock);
printf(" reader %d is reading data!\n", id);
if(data == NULL)
{
printf("data is NULL\n");
}
else
{
printf("data: I = %d, F = %f \n", pdata->I, pdata->F);
}
pthread_rwlock_unlock(&lock);
}

pthread_exit(0);

}

void *write()
{
while(true)
{
pthread_rwlock_wrlock(&lock);
printf(" writer is writind data!\n");
if(pdata == NULL)
{
pdata = new Data(1, 1.1);
printf("Writer is writing data: %d, %f\n", pdata->I, pdata->F);
}
else
{
delete pdata;
pdata = NULL;
printf("writer free the data!");
}

pthread_rwlock_unlock(&lock);
}
pthread_exit(0);
}

void main()
{
pthread_t reader[Read_Num];
pthread_t writer;

for(int i = 0;i<Read_Num;i++)
{
pthread_create(&read[i],NULL,read,(void *)i);
}

pthread_create(writer, NULL, write, NULL);

sleep(1);
return 0;
}

❷ 求助,Linux系統編程,讀者寫者問題

那一時刻即將到來,也許很快
當你們砍倒,燒毀
太多的我們,我們再也不能
給你們足夠的禮物
讓你們繼續燃燒
沒有足夠哈哈的
內燃驅動

❸ 求助,關於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 根筷子的互斥訪問。
示例代碼:

❹ 關於經典問題讀者寫者的讀者優先的演算法

semaphore:rmutex,wmutex=1;readcount=0;
reader(){
wait(rmutex);
if(readcount=0)wait(wmutex);
readcount++;
signal(rmutex);
read;
wait(rmutex);
readcount--;
if(readcount=0)signal(wmutex);
signal(rmutex);
}

writer(){
wait(wmutex);
write;
signal(wmutex);
}

❺ 用多線程同步方法解決讀者寫者問題

這個程序我寫過一個簡單的,如果你還需要,聯系我哈~~

❻ Linux信號量機制實現讀者寫者問題

生產者/消費者問題在windows2000下的實現

一、問題描述

生產者-消費者問題是一個經典的進程同步問題,該問題最早由Dijkstra提出,用以演示他提出的信號量機制。本作業要求設計在同一個進程地址空間內執行的兩個線程。生產者線程生產物品,然後將物品放置在一個空緩沖區中供消費者線程消費。消費者線程從緩沖區中獲得物品,然後釋放緩沖區。當生產者線程生產物品時,如果沒有空緩沖區可用,那麼生產者線程必須等待消費者線程釋放出一個空緩沖區。當消費者線程消費物品時,如果沒有滿的緩沖區,那麼消費者線程將被阻塞,直到新的物品被生產出來。

二、實現代碼

#include <windows.h>
#include <iostream>

const unsigned short SIZE_OF_BUFFER = 10; //緩沖區長度
unsigned short ProctID = 0; //產品號
unsigned short ConsumeID = 0; //將被消耗的產品號
unsigned short in = 0; //產品進緩沖區時的緩沖區下標
unsigned short out = 0; //產品出緩沖區時的緩沖區下標

int g_buffer[SIZE_OF_BUFFER]; //緩沖區是個循環隊列
bool g_continue = true; //控製程序結束
HANDLE g_hMutex; //用於線程間的互斥
HANDLE g_hFullSemaphore; //當緩沖區滿時迫使生產者等待
HANDLE g_hEmptySemaphore; //當緩沖區空時迫使消費者等待

DWORD WINAPI Procer(LPVOID); //生產者線程
DWORD WINAPI Consumer(LPVOID); //消費者線程

int main()
{
//創建各個互斥信號
g_hMutex = CreateMutex(NULL,FALSE,NULL);
g_hEmptySemaphore = CreateSemaphore(NULL,0,SIZE_OF_BUFFER-1,NULL);

//調整下面的數值,可以發現,當生產者個數多於消費者個數時,
//生產速度快,生產者經常等待消費者;反之,消費者經常等待
const unsigned short PRODUCERS_COUNT = 3; //生產者的個數
const unsigned short CONSUMERS_COUNT = 1; //消費者的個數

//總的線程數
const unsigned short THREADS_COUNT = PRODUCERS_COUNT+CONSUMERS_COUNT;

DWORD procerID[CONSUMERS_COUNT]; //生產者線程的標識符
DWORD consumerID[THREADS_COUNT]; //消費者線程的標識符

//創建生產者線程
for (int i=0;i<PRODUCERS_COUNT;++i){
hThreads[i]=CreateThread(NULL,0,Procer,NULL,0,&procerID[i]);
if (hThreads[i]==NULL) return -1;
}
//創建消費者線程
for (int i=0;i<CONSUMERS_COUNT;++i){
hThreads[PRODUCERS_COUNT+i]=CreateThread(NULL,0,Consumer,NULL,0,&consumerID[i]);
if (hThreads[i]==NULL) return -1;
}

while(g_continue){
if(getchar()){ //按回車後終止程序運行
g_continue = false;
}
}

return 0;
}

//生產一個產品。簡單模擬了一下,僅輸出新產品的ID號
void Proce()
{
std::cerr << "Procing " << ++ProctID << " ... ";
std::cerr << "Succeed" << std::endl;
}

//把新生產的產品放入緩沖區
void Append()
{
std::cerr << "Appending a proct ... ";
g_buffer[in] = ProctID;
in = (in+1)%SIZE_OF_BUFFER;
std::cerr << "Succeed" << std::endl;

//輸出緩沖區當前的狀態
for (int i=0;i<SIZE_OF_BUFFER;++i){
std::cout << i <<": " << g_buffer[i];
if (i==in) std::cout << " <-- 生產";
if (i==out) std::cout << " <-- 消費";
std::cout << std::endl;
}
}

//從緩沖區中取出一個產品
void Take()
{
std::cerr << "Taking a proct ... ";
ConsumeID = g_buffer[out];
out = (out+1)%SIZE_OF_BUFFER;
std::cerr << "Succeed" << std::endl;

//輸出緩沖區當前的狀態
for (int i=0;i<SIZE_OF_BUFFER;++i){
std::cout << i <<": " << g_buffer[i];
if (i==in) std::cout << " <-- 生產";
if (i==out) std::cout << " <-- 消費";
std::cout << std::endl;
}
}

//消耗一個產品
void Consume()
{
std::cerr << "Consuming " << ConsumeID << " ... ";
std::cerr << "Succeed" << std::endl;
}

//生產者
DWORD WINAPI Procer(LPVOID lpPara)
{
while(g_continue){
WaitForSingleObject(g_hFullSemaphore,INFINITE);
WaitForSingleObject(g_hMutex,INFINITE);
Proce();
Append();
Sleep(1500);
ReleaseMutex(g_hMutex);
ReleaseSemaphore(g_hEmptySemaphore,1,NULL);
}
return 0;
}

//消費者
DWORD WINAPI Consumer(LPVOID lpPara)
{
while(g_continue){
WaitForSingleObject(g_hEmptySemaphore,INFINITE);
WaitForSingleObject(g_hMutex,INFINITE);
Take();
Consume();
Sleep(1500);
ReleaseMutex(g_hMutex);
ReleaseSemaphore(g_hFullSemaphore,1,NULL);
}
return 0;
}

❼ 讀者寫者問題

qeo

❽ linux下多讀者寫者不加鎖會怎麼樣

當有用戶編輯文件的時候,別的用戶只能讀文件,不能保存修改

❾ 進程互斥問題讀者寫者 reader () { // 讀者進程 while(1){ P (mutex ) ; //互斥

可能會發生錯誤。比如:
1.第一個讀者進入後(此時count==0),p了一下rw。
2.與此同時另一個讀者也進入了,而此時count 尚未更新,仍為0,因此第二個讀者也認為自己是第一個進來的,也去p了rw,但是rw已經被第一個讀者p過了,因此這個讀者會被一直阻塞,直到最後一個讀者離開,釋放了rw後才能被喚醒。若有後續讀者在count更新前進來,那麼這些讀者同樣會被阻塞。
而若設置了mutex互斥信號量,第二個讀者只有在count更新後才能進來,就不會發生上述錯誤。

閱讀全文

與linux讀者寫者問題相關的資料

熱點內容
90壓縮干糧09壓縮干糧 瀏覽:511
android線程池框架 瀏覽:479
手機自帶解壓能解壓哪些文件 瀏覽:802
linux安裝hba驅動 瀏覽:119
java構造函數new 瀏覽:668
怎麼查家裡電器耗電量app 瀏覽:506
原神一直顯示重新連接伺服器怎麼辦 瀏覽:826
一般用途軸流式壓縮機 瀏覽:926
沒學歷的怎麼學編程 瀏覽:901
華為的隱藏相冊無法加密 瀏覽:782
聯通套餐app怎麼設置 瀏覽:752
關於刪除鏈表的演算法描述 瀏覽:894
標准盤和壓縮盤的區別 瀏覽:47
銀行存款驗證碼JAVA編程 瀏覽:111
word轉pdf軟體免費版 瀏覽:139
公主連結安卓台服怎麼下載 瀏覽:550
注冊江蘇銀行app怎麼注冊 瀏覽:800
中興怎麼下載app視頻 瀏覽:679
伺服器審計是什麼 瀏覽:518
華為刪除的app怎麼徹底卸載 瀏覽:574