一生有你llx 阅读(141) 评论(0)
一、读写锁的概念
    1、读写锁与互斥量类似,不过读写锁有更高的并行性。互斥量要么加锁要么不加锁,而且同一时刻只允许一个线程对其加锁。对于一个变量的读取,
    完全可以让多个线程同时进行操作
    2、pthread_rwlock_t     rwlock
    读写锁有三种状态,读模式下加锁,写模式下加锁,不加锁。一次只有一个线程可以占有写模式下的读写锁,但是多个线程可以同时占有读模式的
    读写锁
    3、读写锁在写加锁状态时,在它被解锁之前,所有试图对这个锁加锁的线程都会阻塞。读写锁在读加锁状态时,所有试图以读模式对其加锁的线程
    都会获得访问权,但是如果线程希望以写模式对其加锁,它必须阻塞直到所有的线程释放锁。当读写锁一读模式加锁时,如果有线程试图以写模式对
    其加锁,那么读写锁会阻塞随后的读模式锁请求。这样可以避免读锁长期占用,而写锁达不到请求。
    4、读写锁非常适合对数据结构读次数大于写次数的程序,当它以读模式锁住时,是以共享的方式锁住的;当它以写模式锁住时,是以独占的模式锁
    住的。

二、读写锁的初始化
    1、读写锁在使用之前必须初始化
      int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,  const pthread_rwlockattr_t *restrict attr);
    2、 使用完需要销毁
      int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
      成功返回0 ,失败返回错误码

三、加锁和解锁
    1、读模式加锁       
      int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
      int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
    2、写模式加锁
      int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
      int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
    3、解锁
      int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
    成功返回0

四、手册
PTHREAD_RWLOCK_DESTROY(3P) POSIX Programmer’s ManualPTHREAD_RWLOCK_DESTROY(3P)

PROLOG
       This  manual page is part of the POSIX Programmer’s Manual.  The Linux implementation of this interface may differ (con-
       sult the corresponding Linux manual page for details of Linux behavior), or the interface  may  not  be  implemented  on
       Linux.
        //这只是POSIX的手册,Linux对这个接口的实现可能不一样,或者有的根本没有实现这个接口

NAME
       pthread_rwlock_destroy, pthread_rwlock_init - destroy and initialize a read-write lock object
        //销毁或者初始化一个读写锁

SYNOPSIS
       #include <pthread.h>

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

DESCRIPTION
       The  pthread_rwlock_destroy()  function  shall  destroy  the read-write lock object referenced by rwlock and release any
       resources used by the lock. The effect of subsequent use of the lock is undefined until the  lock  is  reinitialized  by
       another call to pthread_rwlock_init(). An implementation may 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.
        //pthread_rwlock_destroy()将一个读写锁销毁,多次销毁导致未知的结果。销毁一个读写锁会使读写锁变成一个无效值,销毁
        //一个被占用的读写锁导致未知的结果,销毁一个未初始化的读写锁导致未知的结果


       The pthread_rwlock_init() function shall allocate any resources required to use the read-write lock referenced by rwlock
       and initializes the lock to an unlocked state with attributes referenced by attr. If attr is  NULL,  the  default  read-
       write  lock  attributes  shall  be  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 reinitialized.  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.
        //pthread_rwlock_init()会初始化一个读写锁,如果初始化的属性为NULL,那么会用默认的属性初始化读写锁。一个已经
        //被初始化的读写锁可以多次使用,重复的初始化一个已经被初始化的读写锁导致未知的结果。未经过初始化的读写锁在
        //使用的时候会导致未知的结果


       If the pthread_rwlock_init() function fails, rwlock shall not be initialized and the contents of rwlock are undefined.
        //初始化失败,读写锁的内容是未知的

       Only the object referenced by rwlock may be used for performing synchronization. The result of referring  to  copies  of
       that    object    in   calls   to   pthread_rwlock_destroy(),   pthread_rwlock_rdlock(),   pthread_rwlock_timedrdlock(),
       pthread_rwlock_timedwrlock(),  pthread_rwlock_tryrdlock(),   pthread_rwlock_trywrlock(),   pthread_rwlock_unlock(),   or
       pthread_rwlock_wrlock() is undefined.
        //一个被复制过来的读写锁在使用的时候回导致未知的结果

RETURN VALUE
       If  successful,  the pthread_rwlock_destroy() and pthread_rwlock_init() functions shall return zero; otherwise, an error
       number shall be returned to indicate the error.
        //成功返回0,失败返回错误码

       The [EBUSY] and [EINVAL] error checks, if implemented, act as if they were performed immediately  at  the  beginning  of
       processing  for the function and caused an error return prior to modifying the state of the read-write lock specified by
       rwlock.


ERRORS
       The pthread_rwlock_destroy() function may fail if:

       EBUSY  The implementation has detected an attempt to destroy the object referenced by rwlock while it is locked.
        //销毁一个正在被使用的读写锁导致EBUSY

       EINVAL The value specified by rwlock is invalid.
        //读写锁的值是无效的,导致EINVAL

       The pthread_rwlock_init() function shall fail if:

       EAGAIN The system lacked the necessary resources (other than memory) to initialize another read-write lock.
        //系统缺乏除内存之外的资源去初始化读写锁

       ENOMEM Insufficient memory exists to initialize the read-write lock.
        //系统缺乏内存去初始化读写锁

       EPERM  The caller does not have the privilege to perform the operation.
        //调用者没有权利去操作读写锁

       The pthread_rwlock_init() function may fail if:

       EBUSY  The implementation has detected an attempt to reinitialize the object referenced by rwlock, a previously initial-
              ized but not yet destroyed read-write lock.
        //重复的初始化一个已经被初始化的读写锁

       EINVAL The value specified by attr is invalid.
        //属性值是无效的

       These functions shall not return an error code of [EINTR].
        //不会返回EINTR

       The following sections are informative.





PTHREAD_RWLOCK_RDLOCK(3P)  POSIX Programmer’s Manual PTHREAD_RWLOCK_RDLOCK(3P)
PROLOG
       This  manual page is part of the POSIX Programmer’s Manual.  The Linux implementation of this interface may differ (con-
       sult the corresponding Linux manual page for details of Linux behavior), or the interface  may  not  be  implemented  on
       Linux.
        //这只是POSIX的手册,Linux对这个接口的实现可能不一样,或者有的根本没有实现这个接口

NAME
       pthread_rwlock_rdlock, pthread_rwlock_tryrdlock - lock a read-write lock object for reading
        //在读模式下锁住一个读写锁

SYNOPSIS
       #include <pthread.h>
        //包含头文件

       int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
       int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);

DESCRIPTION
       The  pthread_rwlock_rdlock()  function  shall apply 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.
        //pthread_rwlock_rdlock()申请一个读锁,当读写锁没有被写模式占用,而且没有写要求阻塞,那么就会得到读锁

       If the Thread Execution Scheduling option is supported, and the threads involved in the  lock  are  executing  with  the
       scheduling  policies SCHED_FIFO or SCHED_RR, the calling thread shall not acquire the lock if a writer holds the lock or
       if writers of higher or equal priority are blocked on the lock; otherwise, the calling thread shall acquire the lock.
        //如果线程执行的时候支持系统调度,那么锁就会卷入系统调度。如果一个写要求占有锁或者有一个和写要求级别一样的
        //请求正在因为锁阻塞,那么读要求就无法获得锁

       If the Threads Execution Scheduling option is supported, and the threads involved in the lock  are  executing  with  the
       SCHED_SPORADIC scheduling policy, the calling thread shall not acquire the lock if a writer holds the lock or if writers
       of higher or equal priority are blocked on the lock; otherwise, the calling thread shall acquire the lock.


       If the Thread Execution Scheduling option is not supported, it is  implementation-defined  whether  the  calling  thread
       acquires  the lock when a writer does not hold the lock and there are writers blocked on the lock. If a writer holds the
       lock, the calling thread shall not acquire the read lock. If the read lock is not acquired,  the  calling  thread  shall
       block  until  it can acquire the lock.  The calling thread may deadlock if at the time the call is made it holds a write
       lock.
        //如果有写要求占有锁,那么读要求就无法获得锁。如果线程本身占有写锁,它继续申请读锁的时候就会造成死锁

       A thread may hold multiple concurrent read locks on rwlock (that is, successfully call the pthread_rwlock_rdlock() func-
       tion  n  times).  If  so,  the application shall ensure that the thread performs matching unlocks (that is, it calls the
       pthread_rwlock_unlock() function n times).
        //一个线程可以拥有多个读锁,但必须有配对的解锁

       The maximum number of simultaneous read locks that an implementation guarantees can be  applied  to  a  read-write  lock
       shall be implementation-defined. The pthread_rwlock_rdlock() function may fail if this maximum would be exceeded.
        //读锁的最大占有量可以继承过来,如果读锁的最大占有量超过系统设置,那么继续申请读锁就会失败        

       The  pthread_rwlock_tryrdlock()  function  shall  apply a read lock as in the pthread_rwlock_rdlock() function, with the
       exception that the function shall fail if the equivalent pthread_rwlock_rdlock() call would  have  blocked  the  calling
       thread. In no case shall the pthread_rwlock_tryrdlock() function ever block; it always either acquires the lock or fails
       and returns immediately.
        //pthread_rwlock_tryrdlock()会申请一个读锁,如果失败就会阻塞。 pthread_rwlock_tryrdlock()是不会阻塞的
    
       Results are undefined if any of these functions are called with an uninitialized read-write lock.
        //如果一个读写锁为经过初始,那么关于读写锁的一些操作就会失败

       If a signal is delivered to a thread waiting for a read-write lock for reading, upon return from the signal handler  the
       thread resumes waiting for the read-write lock for reading as if it was not interrupted.
        //如果一个信号发送给正在因为读锁阻塞的线程,那么这个线程在从信号处理函数返回之后,仍然继续等待读锁,仿佛
        //从未被中断过

RETURN VALUE
       If  successful,  the pthread_rwlock_rdlock() function shall return zero; otherwise, an error number shall be returned to
       indicate the error.
        //成功返回0,失败返回错误码

       The pthread_rwlock_tryrdlock
       enced by rwlock is acquired. Otherwise, an error number shall be returned to indicate the error.
        

ERRORS
       The pthread_rwlock_tryrdlock() function shall fail if:

       EBUSY  The read-write lock could not be acquired for reading because a writer holds the lock or a writer with the appro-
              priate priority was blocked on it.
        //读锁无法被申请,因为一个写锁占有读写锁,或者有一个写请求在阻塞

       The pthread_rwlock_rdlock() and pthread_rwlock_tryrdlock() functions may fail if:

       EINVAL The value specified by rwlock does not refer to an initialized read-write lock object.
        //一个没有经过初始化的读写锁

       EAGAIN The read lock could not be acquired because the maximum number of read locks for rwlock has been exceeded.
        //读锁已经到达最大请求

       The pthread_rwlock_rdlock() function may fail if:

       EDEADLK
              The current thread already owns the read-write lock for writing.
                //当前线程已经拥有写锁

       These functions shall not return an error code of [EINTR].
        //不会返回EINTR



PTHREAD_RWLOCK_TRYWRLOCK(3PPOSIX Programmer’s ManuPTHREAD_RWLOCK_TRYWRLOCK(3P)
PROLOG
       This  manual page is part of the POSIX Programmer’s Manual.  The Linux implementation of this interface may differ (con-
       sult the corresponding Linux manual page for details of Linux behavior), or the interface  may  not  be  implemented  on
       Linux.
          //这只是POSIX的手册,Linux对这个接口的实现可能不一样,或者有的根本没有实现这个接口

NAME
       pthread_rwlock_trywrlock, pthread_rwlock_wrlock - lock a read-write lock object for writing
        //申请一个写锁

SYNOPSIS
       #include <pthread.h>

       int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
       int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);

DESCRIPTION
       The  pthread_rwlock_trywrlock()  function  shall  apply a write lock like the pthread_rwlock_wrlock() function, with the
       exception that the function shall fail if any thread currently holds rwlock (for reading or writing).
        //申请一个写锁,如果有线程已经拥有的读写锁,那么申请就会失败

       The pthread_rwlock_wrlock() function shall apply a write lock to the read-write lock referenced by rwlock.  The  calling
       thread  acquires  the  write lock if no other thread (reader or writer) holds the read-write lock rwlock. Otherwise, the
       thread shall block until it can acquire the lock. The calling thread may deadlock if at the time the  call  is  made  it
       holds the read-write lock (whether a read or write lock).
        //申请一个写锁,如果没有其他线程占有读写锁就会成功。否则就会阻塞,直到申请成功。如果线程本身已经占有读写锁
        //那么线程就会死锁

       Implementations may favor writers over readers to avoid writer starvation.
        //有一些实现会更偏向于让写锁先获得,避免写锁死等

       Results are undefined if any of these functions are called with an uninitialized read-write lock.
        //一个没有初始化的读写锁,操作会失败

       If  a signal is 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 it was not interrupted.
        //如果一个信号发送给正在因为写锁阻塞的线程,那么这个线程在从信号处理函数返回之后,仍然继续等待写锁,仿佛
        //从未被中断过


RETURN VALUE
       The pthread_rwlock_trywrlock() function shall return zero if the lock for writing on the read-write lock  object  refer-
       enced by rwlock is acquired. Otherwise, an error number shall be returned to indicate the error.
        //申请成功就返回0

       If  successful,  the pthread_rwlock_wrlock() function shall return zero; otherwise, an error number shall be returned to
       indicate the error.
        //成功返回0,失败返回错误码

ERRORS
       The pthread_rwlock_trywrlock() function shall fail if:
       EBUSY  The read-write lock could not be acquired for writing because it was already locked for reading or writing.
        //如果读写锁已经被占用,那么申请就会失败

       The pthread_rwlock_trywrlock() and pthread_rwlock_wrlock() functions may fail if:

       EINVAL The value specified by rwlock does not refer to an initialized read-write lock object.
        //一个没有初始化的读写锁会导致失败

       The pthread_rwlock_wrlock() function may fail if:

       EDEADLK
              The current thread already owns the read-write lock for writing or reading.
                //线程已经占有锁,那么就会造成斯诺

       These functions shall not return an error code of [EINTR].
        //不会返回EINTR


五、实例
    1、程序架构

    2、源代码

点击(此处)折叠或打开

  1. /*DATE:            2015-4-5
  2.  *AUTHOR:        DDDDD
  3.  *DESCRIPTION: 验证可以有多个线程同时拥有读模式下到读写锁
  4.  *    读写锁在使用之前必须初始化
  5.  *    int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,
  6.  *     const pthread_rwlockattr_t *restrict attr);
  7.  *    成功返回0 ,失败返回错误码
  8.  *    
  9.  *    使用完需要销毁
  10.  *    int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
  11.  *    成功返回0 ,失败返回错误码
  12.  *
  13.  *    读模式加锁
  14.  *    int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
  15.  *    int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
  16.  *    写模式加锁
  17.  *    int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
  18.  *    int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
  19.  *    解锁
  20.  *    int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
  21.  */

  22. #include "apue.h"

  23. pthread_rwlock_t rwlock;
  24. int num=0;

  25. void *thread_fun1(void *arg)
  26. {
  27.     int err;

  28.     pthread_rwlock_rdlock(&rwlock);
  29.     printf("thread 1 print num %d\n", num);
  30.     sleep(5);
  31.     printf("thread 1 over\n");

  32.     pthread_rwlock_unlock(&rwlock);
  33.     
  34.     return (void *)1;
  35. }

  36. void *thread_fun2(void *arg)
  37. {
  38.     int err;
  39.     
  40.     pthread_rwlock_wrlock(&rwlock);
  41.     printf("thread 2 print num %d\n", num);
  42.     sleep(5);
  43.     printf("thread 2 is over\n");
  44.     pthread_rwlock_unlock(&rwlock);
  45.     
  46.     return (void *)1;
  47. }

  48. int main()
  49. {
  50.     pthread_t tid1, tid2;
  51.     int err;
  52.     
  53.     err = pthread_rwlock_init(&rwlock, NULL);
  54.     if(err)
  55.     {
  56.         printf("init rwlock failed\n");
  57.         return ;
  58.     }

  59.     err = pthread_create(&tid1, NULL, thread_fun1, NULL);
  60.     if(err)
  61.     {
  62.         printf("create new thread 1 failed\n");
  63.         return ;
  64.     }
  65.     err = pthread_create(&tid2, NULL, thread_fun2, NULL);
  66.     if(err)
  67.     {
  68.         printf("create new thread 2 failed\n");
  69.         return ;
  70.     }

  71.     pthread_join(tid1, NULL);
  72.     pthread_join(tid2, NULL);

  73.     pthread_rwlock_destroy(&rwlock);

  74.     return 0;
  75. }