zoukankan      html  css  js  c++  java
  • linux读写锁

    一.概述                                                   

    读写锁与互斥量的功能类似,对临界区的共享资源进行保护!互斥量一次只让一个线程进入临界区,读写锁比它有更高的并行性。读写锁有以下特点:

    1.如果一个线程用读锁锁定了临界区,那么其他线程也可以用读锁来进入临界区,这样就可以多个线程并行操作。但这个时候,如果再进行写锁加锁就会发生阻塞,写锁请求阻塞后,后面如果继续有读锁来请求,这些后来的读锁都会被阻塞!这样避免了读锁长期占用资源,防止写锁饥饿!

    2.如果一个线程用写锁锁住了临界区,那么其他线程不管是读锁还是写锁都会发生阻塞!

    读写锁的优势往往展现在读操作很频繁,而写操作较少的情况下

    二.函数接口                                           

    1.创建读写锁

    1.1:宏常量初始化

    1 pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;

    1.2:函数初始化

    1 #include <pthread.h>
    2 
    3 int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);

    rwlock:读写锁的pthread_rwlock_t结构指针

    attr:读写锁的属性结构指针。不需要别的属性默认为NULL。

    2.读写锁加锁与解锁

    1 #include <pthread.h>
    2 
    3 int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
    4 int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
    5 int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

    rwlock:创建的读写锁指针

    3.其他类型的加锁

    复制代码
    1 #include <pthread.h>
    2 #include <time.h>
    3 
    4 
    5 int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
    6 int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
    7 
    8 int pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict rwlock, const struct timespec *restrict abs_timeout);
    9 int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rwlock, const struct timespec *restrict abs_timeout);
    复制代码

    try类函数加锁:如果获取不到锁,会立即返回错误EBUSY!

    timed类函数加锁:如果规定的时间内获取不到锁,会返回ETIMEDOUT错误!

    4.销毁读写锁

    #include <pthread.h>
    int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

    应用实例:

    创建4个线程,2个线程读锁,2个线程写锁,观察4个线程进入临界区的顺序:

      1 /**
      2  *  * @file pthread_rwlock.c
      3  *   */
      4 
      5 #include <stdio.h>
      6 #include <stdlib.h>
      7 #include <string.h>
      8 #include <unistd.h>
      9 #include <pthread.h>
     10 using namespace std;
     11 /* 初始化读写锁 */
     12 pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
     13 /* 全局资源 */
     14 class CSingle{
     15 public:
     16   static CSingle& instance(){
     17     static CSingle single;
     18     return single;
     19   }
     20   void setX(int y){
     21     this->x = y;
     22   }
     23   int getX(){
     24     return this->x;
     25   }
     26   int x;
     27 };
     28 int global_num = 10;
     29 
     30 void err_exit(const char *err_msg)
     31 {
     32     printf("error:%s
    ", err_msg);
     33     exit(1);
     34 }
     35 
     36 /* 读锁线程函数 */
     37 void *thread_read_lock(void *arg)
     38 {
     39     char *pthr_name = (char *)arg;
     40 
     41     while (global_num)
     42     {
     43         /* 读加锁 */
     44         pthread_rwlock_rdlock(&rwlock);
     45     
     46         printf("线程%s进入临界区,global_num = %d, X:%d
    ", pthr_name, global_num, CSingle::instance().getX());
     47         sleep(1);
     48         printf("线程%s离开临界区...
    ", pthr_name);
     49 
     50         /* 读解锁 */
     51         pthread_rwlock_unlock(&rwlock);
     52 
     53         sleep(1);
     54     }
     55 
     56     return NULL;
     57 }
     58 
     59 /* 写锁线程函数 */
     60 void *thread_write_lock(void *arg)
     61 {
     62     char *pthr_name = (char *)arg;
     63 
     64     while (global_num)
     65     {
     66         /* 写加锁 */
     67         pthread_rwlock_wrlock(&rwlock);
     68 
     69         /* 写操作 */
     70         --global_num;
     71     CSingle::instance().setX(global_num);
     72         printf("线程%s进入临界区,global_num = %d, X:%d
    ", pthr_name, global_num, CSingle::instance().getX());
     73         sleep(1);
     74         printf("线程%s离开临界区...
    ", pthr_name);
     75 
     76         /* 写解锁 */
     77         pthread_rwlock_unlock(&rwlock);
     78 
     79         sleep(2);
     80     }
     81 
     82     return NULL;
     83 }
     84 
     85 int main(void)
     86 {
     87     pthread_t tid_read_1, tid_read_2, tid_write_1, tid_write_2;
     88 
     89     /* 创建4个线程,2个读,2个写 */
     90     if (pthread_create(&tid_read_1, NULL, thread_read_lock, (void *)"read_1") != 0)
     91         err_exit("create tid_read_1");
     92 
     93     if (pthread_create(&tid_read_2, NULL, thread_read_lock, (void *)("read_2")) != 0)
     94         err_exit("create tid_read_2");
     95 
     96     if (pthread_create(&tid_write_1, NULL, thread_write_lock, (void *)("write_1")) != 0)
     97         err_exit("create tid_write_1");
     98 
     99     if (pthread_create(&tid_write_2, NULL, thread_write_lock, (void *)("write_2")) != 0)
    100         err_exit("create tid_write_2");
    101 
    102     /* 随便等待一个线程,防止main结束 */
    103     if (pthread_join(tid_read_1, NULL) != 0)
    104         err_exit("pthread_join()");
    105     if (pthread_join(tid_read_2, NULL) != 0)
    106         err_exit("pthread_join()");
    107     if (pthread_join(tid_write_1, NULL) != 0)
    108         err_exit("pthread_join()");
    109     if (pthread_join(tid_write_2, NULL) != 0)
    110         err_exit("pthread_join()");
    111 
    112     return 0;
    113 }
    linux读写锁

     pthread中提供的锁有:pthread_mutex_t、pthread_spinlock_t、pthread_rwlock_t。

            pthread_mutex_t是互斥锁,同一瞬间只能有一个线程能够获取锁,其他线程在等待获取锁的时候会进入休眠状态。因此pthread_mutex_t消耗的CPU资源很小,但是性能不高,因为会引起线程切换。

            pthread_spinlock_t是自旋锁,同一瞬间也只能有一个线程能够获取锁,不同的是,其他线程在等待获取锁的过程中并不进入睡眠状态,而是在 CPU上进入“自旋”等待。自旋锁的性能很高,但是只适合对很小的代码段加锁(或短期持有的锁),自旋锁对CPU的占用相对较高。

            pthread_rwlock_t是读写锁,同时可以有多个线程获得读锁,同时只允许有一个线程获得写锁。其他线程在等待锁的时候同样会进入睡眠。读写锁在互斥锁的基础上,允许多个线程“读”,在某些场景下能提高性能。

            对于互斥锁,如果资源已经被占用,资源申请者只能进入睡眠状态。但是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,"自旋"一词就是因此而得名。


    https://blog.csdn.net/JCPGEE/java/article/details/79377948

  • 相关阅读:
    MySQL多表查询回顾
    本地SQL查询
    QBC查询
    HQL查询
    Hibernate多对多操作
    Hibernate一对多操作
    表与表之间关系回顾
    x$bh视图
    dba 和 rdba 转载
    What you can talk
  • 原文地址:https://www.cnblogs.com/guxuanqing/p/7999855.html
Copyright © 2011-2022 走看看