Multithreaded Programming Guide

Using Read-Write Locks

After the attributes for a read-write lock are configured, you initialize the read-write lock. 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–8 Routines that Manipulate Read-Write Locks

Operation 

Related Function Description 

Initialize a read-write lock 

pthread_rwlock_init Syntax

Read lock on read-write lock 

pthread_rwlock_rdlock Syntax

Read lock with a nonblocking read-write lock 

pthread_rwlock_tryrdlock Syntax

Write lock on read-write lock 

pthread_rwlock_wrlock Syntax

Write lock with a nonblocking read-write lock 

pthread_rwlock_trywrlock Syntax

Unlock a read-write lock 

pthread_rwlock_unlock Syntax

Destroy a read-write lock 

pthread_rwlock_destroy Syntax

Initializing a Read-Write Lock

Use pthread_rwlock_init(3C) to initialize the read-write lock referenced by rwlock with the attributes referenced by attr.

pthread_rwlock_init Syntax

#include <pthread.h>

int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, 
          const pthread_rwlockattr_t *restrict attr);

pthread_rwlock_t  rwlock = PTHREAD_RWLOCK_INITIALIZER;

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. After the lock is 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.

In cases where default read-write lock attributes are appropriate, the macro PTHREAD_RWLOCK_INITIALIZER can 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.

pthread_rwlock_init Return Values

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.


EINVAL

Description:

The value specified by attr or rwlock is invalid.

Acquiring the Read Lock on Read-Write Lock

pthread_rwlock_rdlock(3C) applies a read lock to the read-write lock referenced by rwlock.

pthread_rwlock_rdlock Syntax

#include <pthread.h>

int  pthread_rwlock_rdlock(pthread_rwlock_t *rwlock );

The calling thread acquires the read lock if a writer does not hold the lock and no writers are blocked on the lock. Whether the calling thread acquires the lock when a writer does not hold the lock and writers are waiting for the lock is unspecified. If a writer holds the lock, the calling thread does not acquire the read lock. If the read lock is not acquired, the calling thread blocks. The thread does not return from the pthread_rwlock_rdlock() until the thread 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. The Solaris implementation favors writers over readers.

A thread can hold multiple concurrent read locks on rwlock The thread can successfully call pthread_rwlock_rdlock() n times. The thread must call pthread_rwlock_unlock() n times to perform matching unlocks.

Results are undefined if pthread_rwlock_rdlock() is called with an uninitialized read-write lock.

A thread signal handler processes a signal delivered to a thread waiting for a read-write lock. On return from the signal handler, the thread resumes waiting for the read-write lock for reading as if the thread was not interrupted.

pthread_rwlock_rdlock Return Values

If successful, pthread_rwlock_rdlock() returns zero. Otherwise, an error number is returned to indicate the error.


EINVAL

Description:

The value specified by attr or rwlock is invalid.

Acquiring a Read Lock on a Read-Write Lock Before a Specified Absolute Time

The pthread_rwlock_timedrdlock(3C) function applies a read lock to the read-write lock referenced by rwlock as in the pthread_rwlock_rdlock() function.

pthread_rwlock_timedrdlock Syntax

#include <pthread.h>
#include <time.h>

int  pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict rwlock,
          const struct timespec *restrict abs_timeout);

If the lock cannot be acquired without waiting for other threads to unlock the lock, this wait will be terminated when the specified timeout expires. The timeout expires when the absolute time specified by abs_timeout passes, as measured by the CLOCK_REALTIME clock (that is, when the value of that clock equals or exceeds abs_timeout), or if the absolute time specified by abs_timeout has already been passed at the time of the call.

The resolution of the timeout is the resolution of the CLOCK_REALTIME clock. The timespec data type is defined in the <time.h> header. Under no circumstances does the function fail with a timeout if the lock can be acquired immediately. The validity of the timeout parameter need not be checked if the lock can be immediately acquired.

If a signal that causes a signal handler to be executed is delivered to a thread blocked on a read-write lock with a call to pthread_rwlock_timedrdlock(), upon return from the signal handler the thread resumes waiting for the lock as if it was not interrupted.

The calling thread might deadlock if at the time the call is made it holds a write lock on rwlock.

The pthread_rwlock_reltimedrdlock_np() function is identical to the pthread_rwlock_timedrdlock() function, except that the timeout is specified as a relative time interval.

pthread_rwlock_timedrdlock Return Values

If successful, returns 0 if the lock for writing on the read-write lock object referenced by rwlock is acquired. Otherwise, an error number is returned to indicate the error.


ETIMEDOUT

Description:

The lock could not be acquired before the specified timeout expired.


EAGAIN

Description:

The read lock could not be acquired because the maximum number of read locks for lock would be exceeded.


EDEADLK

Description:

The calling thread already holds the rwlock.


EINVAL

Description:

The value specified by rwlock does not refer to an initialized read-write lock object, or the timeout nanosecond value is less than zero or greater than or equal to 1,000 million.

Acquiring a Non-Blocking Read Lock on a Read-Write Lock

pthread_rwlock_tryrdlock(3C) applies a read lock as in pthread_rwlock_rdlock() with the exception that the function fails if any thread holds a write lock on rwlock or writers are blocked on rwlock.

pthread_rwlock_tryrdlock Syntax

#include <pthread.h>

int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);

pthread_rwlock_tryrdlock Return Values

pthread_rwlock_tryrdlock() returns zero if the lock for reading on the read-write lock object referenced by rwlock is acquired. If the lock is not acquired, an error number is returned to indicate the error.


EBUSY

Description:

The read-write lock could not be acquired for reading because a writer holds the lock or was blocked on it.

Acquiring the Write Lock on a Read-Write Lock

pthread_rwlock_wrlock(3C) applies a write lock to the read-write lock referenced by rwlock.

pthread_rwlock_wrlock Syntax

#include <pthread.h>

int  pthread_rwlock_wrlock(pthread_rwlock_t *rwlock );

The calling thread acquires the write lock if no other reader thread or writer thread holds the read-write lock rwlock. Otherwise, the thread blocks. The thread does not return from the pthread_rwlock_wrlock() call until the thread can acquire the lock. Results are undefined if the calling thread holds the read-write lock, either a read lock or write lock, at the time the call is made.

Implementations are allowed to favor writers over readers to avoid writer starvation. The Solaris implementation favors writers over readers.

Results are undefined if pthread_rwlock_wrlock() is called with an uninitialized read-write lock.

The thread signal handler processes a signal delivered to a thread waiting for a read-write lock for writing. Upon return from the signal handler, the thread resumes waiting for the read-write lock for writing as if the thread was not interrupted.

pthread_rwlock_wrlock Return Values

pthread_rwlock_rwlock() returns zero if the lock for writing on the read-write lock object referenced by rwlock is acquired. If the lock is not acquired, an error number is returned to indicate the error.

Acquiring a Non-blocking Write Lock on a Read-Write Lock

pthread_rwlock_trywrlock(3C) applies a write lock like pthread_rwlock_wrlock(), with the exception that the function fails if any thread currently holds rwlock, for reading or writing.

pthread_rwlock_trywrlock Syntax

#include <pthread.h>

int pthread_rwlock_trywrlock(pthread_rwlock_t  *rwlock);

Results are undefined if pthread_rwlock_trywrlock() is called with an uninitialized read-write lock.

pthread_rwlock_trywrlock Return Values

If successful, pthread_rwlock_trywrlock() returns zero if the lock for writing on the read-write lock object referenced by rwlock is acquired. Otherwise, an error number is returned to indicate the error.


EBUSY

Description:

The read-write lock could not be acquired for writing because the read-write lock is already locked for reading or writing.

Acquiring a Write Lock on a Read-Write Lock Before a Specified Absolute Time

The pthread_rwlock_timedwrlock(3C) function applies a write lock to the read-write lock referenced by rwlock as in the pthread_rwlock_wrlock() function, but attempts to apply the lock only until a specified absolute time.

pthread_rwlock_timedwrlock Syntax

#include <pthread.h>
#include <time.h>

int  pthread_rwlock_timedwrlock(pthread_rwlock_t   *restrict rwlock, 
     const struct timespec *restrict abs_timeout);

The calling thread acquires the write lock if no other reader thread or writer thread holds the read-write lock rwlock. If the lock cannot be acquired without waiting for other threads to unlock the lock, this wait will be terminated when the specified timeout expires. The timeout expires when the absolute time specified by abs_timeoutpasses, as measured by the CLOCK_REALTIME clock (that is, when the value of that clock equals or exceeds abs_timeout) or if the absolute time specified by abs_timeout has already been passed at the time of the call. The pthread_rwlock_reltimedwrlock_np() function is identical to the pthread_rwlock_timedwrlock() function, except that the timeout is specified as a relative time interval.

pthread_rwlock_timedwrlock Returns

If successful, returns 0 if the lock for writing on the read-write lock object referenced by rwlock is acquired. Otherwise, an error number is returned to indicate the error.


ETIMEDOUT

Description:

The lock could not be acquired before the specified timeout expired.


EDEADLK

Description:

The calling thread already holds the rwlock.


EINVAL

Description:

The value specified by rwlock does not refer to an initialized read-write lock object, or the timeout nanosecond value is less than zero or greater than or equal to 1,000 million.

Unlocking a Read-Write Lock

pthread_rwlock_unlock(3C) releases a lock held on the read-write lock object referenced by rwlock.

pthread_rwlock_unlock Syntax

#include <pthread.h>

int pthread_rwlock_unlock (pthread_rwlock_t  *rwlock);

Results are undefined if the read-write lock rwlock is not held by the calling thread.

If pthread_rwlock_unlock() is called to release a read lock from the read-write lock object, and other read locks are currently held on this lock object, the object remains in the read locked state. If pthread_rwlock_unlock() releases the calling thread's last read lock on this read-write lock object, the calling thread is no longer an owner of the object. If pthread_rwlock_unlock() releases the last read lock for this read-write lock object, the read-write lock object is put in the unlocked state with no owners.

If pthread_rwlock_unlock() is called to release a write lock for this read-write lock object, the lock object is put in the unlocked state with no owners.

If pthread_rwlock_unlock() unlocks the read-write lock object and multiple threads are waiting to acquire the lock object for writing, the scheduling policy determines which thread acquires the object for writing. If multiple threads are waiting to acquire the read-write lock object for reading, the scheduling policy determines the order the waiting threads acquire the object for reading. If multiple threads are blocked on rwlock for both read locks and write locks, whether the readers or the writer acquire the lock first is unspecified.

Results are undefined if pthread_rwlock_unlock() is called with an uninitialized read-write lock.

pthread_rwlock_unlock Return Values

If successful, pthread_rwlock_unlock() returns zero. Otherwise, an error number is returned to indicate the error.

Destroying a Read-Write Lock

pthread_rwlock_destroy(3C) destroys the read-write lock object referenced by rwlock and releases any resources used by the lock.

pthread_rwlock_destroy Syntax

#include <pthread.h>

int pthread_rwlock_destroy(pthread_rwlock_t **rwlock);

The effect of subsequent use of the lock is undefined until the lock is re-initialized by another call to pthread_rwlock_init(). An implementation can cause pthread_rwlock_destroy() to set the object referenced by rwlock to an invalid value. Results are undefined if pthread_rwlock_destroy() is called when any thread holds rwlock. Attempting to destroy an uninitialized read-write lock results in undefined behavior. A destroyed read-write lock object can be re-initialized using pthread_rwlock_init(). The results of otherwise referencing the read-write lock object after the lock object has been destroyed are undefined.

pthread_rwlock_destroy Return Values

If successful, pthread_rwlock_destroy() returns zero. Otherwise, an error number is returned to indicate the error.


EINVAL

Description:

The value specified by attr or rwlock is invalid.