Multithreading (read and write lock)

Posted by Fribbles on Fri, 01 May 2020 13:20:56 +0200

[notice: All Rights Reserved. Please reprint. Do not use for commercial purposes. Contact email: feixiaoxing@163.com]


When writing multithreads, it's very common to have one. That is, there are few opportunities for public data modification. Compared with rewriting, their chances of reading are much higher. Generally speaking, the process of reading is often accompanied by the operation of searching, which takes a long time. Adding a lock to this code segment will greatly reduce the efficiency of our program. Is there a way to deal with the situation of more reading and less writing?
Yes, that's the read-write lock.

(1) first, let's define the basic data structure.

  1. typedef struct _RWLock  
  2. {  
  3.     int count;  
  4.     int state;  
  5.     HANDLE hRead;  
  6.     HANDLE hWrite;  
  7. }RWLock;     
At the same time, to determine whether the current lock is in read or write state, we need to define an enumerator,
  1. typedef enum  
  2. {  
  3.     STATE_EMPTY = 0,  
  4.     STATE_READ,  
  5.     STATE_WRITE  
  6. };  
(2) initialize data structure

  1. RWLock* create_read_write_lock(HANDLE hRead, HANDLE hWrite)  
  2. {  
  3.     RWLock* pRwLock = NULL;  
  4.   
  5.     assert(NULL != hRead && NULL != hWrite);  
  6.     pRwLock = (RWLock*)malloc(sizeof(RWLock));  
  7.     
  8.     pRwLock->hRead = hRead;  
  9.     pRwLock->hWrite = hWrite;  
  10.     pRwLock->count = 0;  
  11.     pRwLock->state = STATE_EMPTY;  
  12.     return pRwLock;  
  13. }  
(3) acquire read lock

  1. void read_lock(RWLock* pRwLock)  
  2. {  
  3.     assert(NULL != pRwLock);  
  4.       
  5.     WaitForSingleObject(pRwLock->hRead, INFINITE);  
  6.     pRwLock->counnt ++;  
  7.     if(1 == pRwLock->count){  
  8.         WaitForSingleObject(pRwLock->hWrite, INFINITE);  
  9.         pRwLock->state = STATE_READ;  
  10.     }  
  11.     ReleaseMutex(pRwLock->hRead);  
  12. }  
(4) acquire write lock
  1. void write_lock(RWLock* pRwLock)  
  2. {  
  3.     assert(NULL != pRwLock);  
  4.   
  5.     WaitForSingleObject(pRwLock->hWrite, INFINITE);  
  6.     pRwLock->state = STATE_WRITE;  
  7. }  
(5) release the read-write lock
  1. void read_write_unlock(RWLock* pRwLock)  
  2. {  
  3.     assert(NULL != pRwLock);  
  4.   
  5.     if(STATE_READ == pRwLock->state){  
  6.         WaitForSingleObject(pRwLock->hRead, INFINITE);  
  7.         pRwLock->count --;  
  8.         if(0 == pRwLock->count){  
  9.             pRwLock->state = STATE_EMPTY;  
  10.             ReleaseMutex(pRwLock->hWrite);  
  11.         }  
  12.         ReleaseMutex(pRwLock->hRead);  
  13.     }else{  
  14.         pRwLock->state = STATE_EMPTY;  
  15.         ReleaseMutex(pRwLock->hWrite);  
  16.     }  
  17.       
  18.     return;  
  19. }  

Article summary:
(1) the advantage of read-write lock can be maximized only when there are two conditions: more read and less write, and long code segment running time;
(2) any modification of public data must be completed in the lock;
(3) the read-write lock has its own application place, so it is very important to choose a suitable application environment;
(4) it's easy to make mistakes in writing and reading locks. Friends should practice more;
(5) the read lock and the write lock must be used separately, otherwise the effect will not be achieved.

Topics: less