Read-Write Lock Attributes
Read-write locks permit concurrent reads and exclusive writes to a protected shared resource. The read-write lock is a single entity that can be locked in read or write mode. To modify a resource, a thread must first acquire the exclusive write lock. An exclusive write lock is not permitted until all read locks have been released.
Database access can be synchronized with a read-write lock. Read-write locks support concurrent reads of database records because the read operation does not change the record's information. When the database is to be updated, the write operation must acquire an exclusive write lock.
To change the default read-write lock attributes, you can declare and initialize an attribute object. Often, the read-write lock attributes are set up in one place at the beginning of the application so they can be located quickly and modified easily. The following table lists the functions discussed in this section that manipulate read-write lock attributes.
See "Similar Synchronization Functions--Read-Write Locks" for the Solaris threads implementation of read-write locks.
Table 4-8 Routines for Read-Write Lock Attributes
Operation | Destination Discussion | |
---|---|---|
Initialize a read-write lock attribute | ||
Destroy a read-write lock attribute | ||
Set a read-write lock attribute | ||
Get a read-write lock attribute |
Initialize a Read-Write Lock Attribute
pthread_rwlockattr_init(3THR)
#include <pthread.h> int pthread_rwlockattr_init(pthread_rwlockattr_t *attr); |
pthread_rwlockattr_init(3THR) initializes a read-write lock attributes object attr with the default value for all of the attributes defined by the implementation.
Results are undefined if pthread_rwlockattr_init is called specifying an already initialized read-write lock attributes object. After a read-write lock attributes object has been used to initialize one or more read-write locks, any function affecting the attributes object (including destruction) does not affect any previously initialized read-write locks.
Return Values
If successful, pthread_rwlockattr_init() returns zero. Otherwise, an error number is returned to indicate the error.
Insufficient memory exists to initialize the rwlock attributes object.
Destroy a Read-Write Lock Attribute
pthread_rwlockattr_destroy(3THR)
#include <pthread.h> int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr); |
pthread_rwlockattr_destroy(3THR) destroys a read-write lock attributes object. The effect of subsequent use of the object is undefined until the object is re-initialized by another call to pthread_rwlockattr_init() An implementation can cause pthread_rwlockattr_destroy() to set the object referenced by attr to an invalid value.
Return Values
If successful, pthread_rwlockattr_destroy() returns zero. Otherwise, an error number is returned to indicate the error.
The value specified by attr is invalid.
Set a Read-Write Lock Attribute
pthread_rwlockattr_setpshared(3THR)
#include <pthread.h> int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *attr, int pshared); |
pthread_rwlockattr_setpshared(3THR) sets the process-shared read-write lock attribute.
PTHREAD_PROCESS_SHARED
Permits a read-write lock to be operated on by any thread that has access to the memory where the read-write lock is allocated, even if the read-write lock is allocated in memory that is shared by multiple processes.
PTHREAD_PROCESS_PRIVATE
The read-write lock will only be operated upon by threads created within the same process as the thread that initialized the read-write lock; if threads of differing processes attempt to operate on such a read-write lock, the behavior is undefined. The default value of the process-shared attribute is PTHREAD_PROCESS_PRIVATE.
Return Value
If successful, pthread_rwlockattr_setpshared() returns zero. Otherwise, an error number is returned to indicate the error.
The value specified by attr or pshared is invalid.
Get a Read-Write Lock Attribute
pthread_rwlockattr_getpshared(3THR)
#include <pthread.h> int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *attr, int *pshared); |
pthread_rwlockattr_getpshared(3THR) gets the process-shared read-write lock attribute.
pthread_rwlockattr_getpshared() obtains the value of the process-shared attribute from the initialized attributes object referenced by attr.
Return Value
If successful, pthread_rwlockattr_getpshared() returns zero. Otherwise, an error number is returned to indicate the error.
The value specified by attr or pshared is invalid.
Using Read-Write Locks
After the attributes for a read-write lock are configured, you initialize the read-write lock itself. The following functions are used to initialize or destroy, lock or unlock, or try to lock a read-write lock. The following table lists the functions discussed in this section that manipulate read-write locks.
Table 4-9 Routines that Manipulate Read-Write Locks
Operation | Destination Discussion | |
---|---|---|
Initialize a read-write lock | ||
Read lock on read-write lock | ||
Read lock with a nonblocking read-write lock | ||
Write lock on read-write lock | ||
Write lock with a nonblocking read-write lock | ||
Unlock a read-write lock | ||
Destroy a read-write lock |
Initialize a Read-Write Lock
pthread_rwlock_init(3THR)
#include <pthread.h> int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr); pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; |
Use pthread_rwlock_init(3THR) to initialize the read-write lock referenced by rwlock with the attributes referenced by attr. If attr is NULL, the default read-write lock attributes are used; the effect is the same as passing the address of a default read-write lock attributes object. Once initialized, the lock can be used any number of times without being re-initialized. On successful initialization, the state of the read-write lock becomes initialized and unlocked. Results are undefined if pthread_rwlock_init() is called specifying an already initialized read-write lock. Results are undefined if a read-write lock is used without first being initialized. (For Solaris threads, see "rwlock_init(3THR)".)
In cases where default read-write lock attributes are appropriate, the macro PTHREAD_RWLOCK_INITIALIZER can be used to initialize read-write locks that are statically allocated. The effect is equivalent to dynamic initialization by a call to pthread_rwlock_init() with the parameter attr specified as NULL, except that no error checks are performed.
Return Value
If successful, pthread_rwlock_init() returns zero. Otherwise, an error number is returned to indicate the error.
If pthread_rwlock_init() fails, rwlock is not initialized and the contents of rwlock are undefined.
The value specified by attr or rwlock is invalid.
Read Lock on Read-Write Lock
pthread_rwlock_rdlock(3THR)
#include <pthread.h> int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock ); |
pthread_rwlock_rdlock(3THR) applies a read lock to the read-write lock referenced by rwlock. The calling thread acquires the read lock if a writer does not hold the lock and there are no writers blocked on the lock. It is unspecified whether the calling thread acquires the lock when a writer does not hold the lock and there are writers waiting for the lock. If a writer holds the lock, the calling thread will not acquire the read lock. If the read lock is not acquired, the calling thread blocks (that is, it does not return from the pthread_rwlock_rdlock()) until it can acquire the lock. Results are undefined if the calling thread holds a write lock on rwlock at the time the call is made.
Implementations are allowed to favor writers over readers to avoid writer starvation. (For instance, the Solaris threads implementation favors writers over readers. See "rw_rdlock(3THR)".)
A thread can hold multiple concurrent read locks on rwlock (that is, successfully call pthread_rwlock_rdlock() n times) If so, the thread must perform matching unlocks (that is, it must call pthread_rwlock_unlock() n times).
Results are undefined if pthread_rwlock_rdlock() is called with an uninitialized read-write lock.
If a signal is delivered to a thread waiting for a read-write lock for reading, on return from the signal handler the thread resumes waiting for the read-write lock for reading as if it was not interrupted.