In a previous blog post on Linux multithreaded programming, only the mutex, condition variables for thread synchronization were mentioned, and no read-write locks (Read-write Lock) were mentioned.
This article is mainly organized from the following articles:
Read-write Lock (Read-write lock) mechanism-----The solution of multithreading synchronization problem
Please use a common mutex program to implement a read-write lock
Read/write Lock
Read-write locks are more adaptable than mutexes, and multiple threads can consume read-mode reads and writes at the same time, but only one thread consumes write-mode read-write locks.
1) When the read-write lock is a write-lock state , all threads attempting to lock the lock are blocked until the lock is unlocked.
2) When the read-write lock is in the locking state , all threads attempting to lock it in read mode can gain access, but the thread that is chained to it in write mode will block;
3) When the read-write lock is in the reading Mode lock state , if there is another thread attempting to lock in write mode , the read- write lock usually blocks the subsequent read mode lock request , which avoids the long-term use of the read mode lock, while the waiting write mode lock request is blocked for a long time;
This lock applies when the data structure is read more often than it is written .
read-write lock APIInitialize and destroy
There are two ways to initialize a read-write lock variable, one is to initialize it by assigning a static read-write lock to a constant pthread_rwlock_initializer, and the other is to initialize it dynamically by calling Pthread_rwlock_init (). When a thread no longer needs a read-write lock, the lock can be destroyed by calling Pthread_rwlock_destroy. The function prototypes are as follows:
#include <pthread.h>intconst pthread_rwlockattr_t *restrict attr); int Pthread_rwlock_destroy (pthread_rwlock_t *rwlock); // Success returns 0, error number is returned.
Before releasing the memory occupied by a read-write lock, the read-write lock is cleaned by Pthread_rwlock_destroy and the resources allocated by Pthread_rwlock_init are freed. When initializing a read-write lock, if the property pointer attr is a null pointer, it represents the default property, and if you want to use a non-default property, use the following two functions:
int pthread_rwlockattr_init (pthread_rwlockattr_t *attr); int Pthread_rwlockattr_destroy (pthread_rwlockatttr_t *attr); // successful return 0, error code returned.
It is also necessary to note that the lock is in a non-locked state after the initialization of the read-write lock is complete. When a Property object with a data type of pthread_rwlockattr_t is initialized, it is possible to enable or disable a particular property by using a different function tune.
Read locking and Write plus lock
The data type of a read-write lock is pthread_rwlock_t, and if a variable in that data type is statically allocated, it can be initialized by assigning it a constant value Pthread_rwlock_initializar. Pthread_rwlock_rdlock () is used to obtain a read-out lock, blocking the calling thread if the corresponding read-out lock is already occupied by a writer. Pthread_rwlock_wrlock () is used to obtain a write lock that, if the corresponding write lock is already occupied by another writer or one or more readers, blocks the calling thread; Pthread_rwlock_unlock () is used to release a read or write lock. The function prototypes are as follows:
#include <pthread.h>int pthread_rwlock_rdlock (pthread_rwlock_t *rwlock); int pthread_rwlock_wrlock (pthread_rwlock_t *rwlock); int pthread_rwlock_unlock (pthread_rwlock_t *rwlock); // Success returns 0, error number is returned.
It is important to note that the operation of the two functions in which the lock is acquired is a blocking operation, that is, if the lock is not obtained, then the calling thread does not return immediately, but instead blocks execution. In the case of writing, this blocking approach may not be very suitable, so the next step is to introduce two functions Pthread_rwlock_tryrdlock () and Pthread_rwlock_trywrlock () that take a non-blocking approach to read and write locks, When a lock is acquired in a non-blocking manner, a ebusy error is returned immediately if it cannot be obtained immediately, instead of putting the calling thread into a sleep wait. The function prototypes are as follows:
#include <pthread.h>int pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock); int pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock); // Success returns 0, error number is returned.
Implementing a read-write lock with a mutex
The pseudo code is as follows:
1Count_mutex =mutex_init ();2Write_mutex =mutex_init ();3Read_count =0;4 5 voidread_lock{6 Lock(Count_mutex);7read_count++;8 if(Read_count = =1) {9 Lock(Write_mutex);Ten } One unlock (Count_mutex); A } - - voidread_unlock{ the Lock(Count_mutex); -read_count--; - if(Read_count = =0) { - unlock (Write_mutex); + } - unlock (Count_mutex); + } A at voidwrite_lock{ - Lock(Write_mutex); - } - - voidwrite_unlock{ - unlock (Write_mutex); in}
Read-write lock mechanism