c++读写锁--读者写者问题
作者:互联网
又名:共享-互斥锁,多读者-单写者锁。
允许多个读者进入临界区,因为只读数据是安全的;
只允许单写者进入临界区。
所以,读者进入临界区时,第一个读者对临界区资源加一次锁,最后一个读者解锁(所以又名:共享锁,读锁);写者进入临界区时,每次都需要对临界区加锁解锁(又名:排他锁,写锁)。
注:semaphore信号量的值为1,等同于互斥量使用。
第一种实现,读优先
1 semaphore resource=1; 2 semaphore rmutex=1; 3 readcount=0; 4 5 /* 6 resource.P() is equivalent to wait(resource) 7 resource.V() is equivalent to signal(resource) 8 rmutex.P() is equivalent to wait(rmutex) 9 rmutex.V() is equivalent to signal(rmutex) 10 */ 11 12 writer() { 13 resource.P(); //Lock the shared file for a writer 14 15 <CRITICAL Section> 16 // Writing is done 17 18 <EXIT Section> 19 resource.V(); //Release the shared file for use by other readers. Writers are allowed if there are no readers requesting it. 20 } 21 22 reader() { 23 rmutex.P(); //Ensure that no other reader can execute the <Entry> section while you are in it 24 <CRITICAL Section> 25 readcount++; //Indicate that you are a reader trying to enter the Critical Section 26 if (readcount == 1) //Checks if you are the first reader trying to enter CS 27 resource.P(); //If you are the first reader, lock the resource from writers. Resource stays reserved for subsequent readers 28 <EXIT CRITICAL Section> 29 rmutex.V(); //Release 30 31 // Do the Reading 32 33 rmutex.P(); //Ensure that no other reader can execute the <Exit> section while you are in it 34 <CRITICAL Section> 35 readcount--; //Indicate that you are no longer needing the shared resource. One fewer reader 36 if (readcount == 0) //Checks if you are the last (only) reader who is reading the shared file 37 resource.V(); //If you are last reader, then you can unlock the resource. This makes it available to writers. 38 <EXIT CRITICAL Section> 39 rmutex.V(); //Release 40 }
第一个读者进入时,将资源加锁,从而安全访问临界区,不会被写者修改;由于需要对读者计数,所以需要一个rmutex互斥量来保护readcount修改的安全。读者数为0时,释放资源锁。
第二种实现,写优先
1 int readcount, writecount; //(initial value = 0) 2 semaphore rmutex, wmutex, readTry, resource; //(initial value = 1) 3 4 //READER 5 reader() { 6 <ENTRY Section> 7 readTry.P(); //Indicate a reader is trying to enter 8 rmutex.P(); //lock entry section to avoid race condition with other readers 9 readcount++; //report yourself as a reader 10 if (readcount == 1) //checks if you are first reader 11 resource.P(); //if you are first reader, lock the resource 12 rmutex.V(); //release entry section for other readers 13 readTry.V(); //indicate you are done trying to access the resource 14 15 <CRITICAL Section> 16 //reading is performed 17 18 <EXIT Section> 19 rmutex.P(); //reserve exit section - avoids race condition with readers 20 readcount--; //indicate you're leaving 21 if (readcount == 0) //checks if you are last reader leaving 22 resource.V(); //if last, you must release the locked resource 23 rmutex.V(); //release exit section for other readers 24 } 25 26 //WRITER 27 writer() { 28 <ENTRY Section> 29 wmutex.P(); //reserve entry section for writers - avoids race conditions 30 writecount++; //report yourself as a writer entering 31 if (writecount == 1) //checks if you're first writer 32 readTry.P(); //if you're first, then you must lock the readers out. Prevent them from trying to enter CS 33 wmutex.V(); //release entry section 34 resource.P(); //reserve the resource for yourself - prevents other writers from simultaneously editing the shared resource 35 <CRITICAL Section> 36 //writing is performed 37 resource.V(); //release file 38 39 <EXIT Section> 40 wmutex.P(); //reserve exit section 41 writecount--; //indicate you're leaving 42 if (writecount == 0) //checks if you're the last writer 43 readTry.V(); //if you're last writer, you must unlock the readers. Allows them to try enter CS for reading 44 wmutex.V(); //release exit section 45 }
写者优先,所以当第一个写者进入时,尝试对读者加锁,让后面的读者阻塞,即readTry.P();增加了writecount写者计数,不为0时,不会让读者进入,即readTry.V();写者对临界区的访问仍然需要互斥进行,即resource.P(),resource.V();wmutex是为了保护计数的。
第三种实现,读者写者都公平
1 int readcount; // init to 0; number of readers currently accessing resource 2 3 // all semaphores initialised to 1 4 semaphore resource; // controls access (read/write) to the resource 5 semaphore rmutex; // for syncing changes to shared variable readcount 6 semaphore serviceQueue; // FAIRNESS: preserves ordering of requests (signaling must be FIFO) 7 8 //READER 9 reader() { 10 <ENTRY Section> 11 serviceQueue.P(); // wait in line to be serviced 12 rmutex.P(); // request exclusive access to readcount 13 readcount++; // update count of active readers 14 if (readcount == 1) // if I am the first reader 15 resource.P(); // request resource access for readers (writers blocked) 16 serviceQueue.V(); // let next in line be serviced 17 rmutex.V(); // release access to readcount 18 19 <CRITICAL Section> 20 //reading is performed 21 22 <EXIT Section> 23 rmutex.P(); // request exclusive access to readcount 24 readcount--; // update count of active readers 25 if (readcount == 0) // if there are no readers left 26 resource.V(); // release resource access for all 27 rmutex.V(); // release access to readcount 28 } 29 30 //WRITER 31 writer() { 32 <ENTRY Section> 33 serviceQueue.P(); // wait in line to be serviced 34 resource.P(); // request exclusive access to resource 35 serviceQueue.V(); // let next in line be serviced 36 37 <CRITICAL Section> 38 // writing is performed 39 40 <EXIT Section> 41 resource.V(); // release resource access for next reader/writer 42 }
与第一种读优先比较,多了一个serviceQueue互斥锁,读者写者同时请求这个互斥锁,以此达到公平竞争的目的。
Reference:
https://en.wikipedia.org/wiki/Readers%E2%80%93writers_problem
标签:readcount,resource,readers,--,写者,c++,reader,release,rmutex 来源: https://www.cnblogs.com/mingbujian/p/14098693.html