读写锁与互斥量类似,不过读写锁允许更高的并行性。互斥量要么是锁住状态,要么就是不加锁状态,而且一次只有一个线程可以对其加锁。读写锁可以有三种状态:读模式下加锁状态,写模式下加锁状态,不加锁状态。一次只有一个线程可以占有写模式的读写锁,但是锁哥线程可以同时占有读模式的读写锁。

       当读写锁是写加锁状态时,在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞。当读写锁在读加锁状态时,所有试图以读模式对他进行加锁的线程都可以得到访问权限,但是任何希望以写模式对此锁进行加锁的线程都会被阻塞,直到所有的线程释放他们的读锁为止。当读写锁处于读模式锁住的状态,而这时有一个线程试图以写模式获取锁时,读写锁通常会阻塞随后的读模式锁请求。这样可以避免读模式锁长期占用,而等待的写模式锁请求一直得不到满足。

       读写锁非常适合于对数据结构读的次数远大于写的情况。当读写锁在写模式下,它所保护的数据结构就可以被安全的修改。因为一次只有一个线程可以在写模式下拥有这个锁。当读写锁在读模式下时,只要线程先获取了读模式下的读写锁,该锁所保护的数据结构就可以被多个获得读模式锁的线程读取。

      读写锁也叫作共享互斥锁,当读写锁是读模式锁住时,就可以说成是以共享模式锁住的。当它是写模式锁住的时候,就可以说成是以互斥模式锁住的。

      读写锁在使用之前必须初始化,在使用完后必须销毁,函数如下:

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

      int pthread_rwlock_destroy(pthread_rwlock_t *rwlock)

      要在读模式下锁定读写锁,需要调用pthread_rwlock_rdlock,要在写模式下锁定读写锁,需要调用pthred_rwlock_wrlock,都需要调用pthread_rwlock_unlock来进行解锁。函数如下:


      int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)

      int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)

      int pthread_rwlock_unlock(pthread_rwlock_t *rwlock)


下面我们来写一个小程序来练练手:

       在下面的程序中,我们定义了一个全局变量,写着不断地对它进行累加,而读者不断读取它。

   #include <stdio.h>
   #include <stdlib.h>
   #include <pthread.h>
   
   pthread_rwlock_t lock;
   int g_val=0;
   
   void *reader(void *arg)
   {
      while(1)
      {
          pthread_rwlock_rdlock(&lock);
          printf("%d\n",g_val);
          pthread_rwlock_unlock(&lock);
      }
  }
  
  void *writer(void *arg)
  {
      while(1)
      {
          pthread_rwlock_wrlock(&lock);
          g_val++;                                                                                                                                                    
          pthread_rwlock_unlock(&lock);
          sleep(1);
      }
  }
  
  int main()
  {
      pthread_rwlock_init(&lock,NULL);
  
      pthread_t tid1,tid2;
      pthread_create(&tid1,NULL,reader,NULL);
      pthread_create(&tid2,NULL,writer,NULL);
  

      pthread_join(tid1,NULL);
      pthread_join(tid2,NULL);
  
     pthread_rwlock_destroy(&lock);                                                                                                                       
      return 0;
  }


运行结果如下:(结果显示不全)

wKioL1ccxQzThamwAAASqqkQIKs069.png

结果是从1到逐渐增大不停地打印,我只截取了一部分。