Linux---线程读写锁详解及代码实现

简介: Linux---线程读写锁详解及代码实现

一、读写锁原理

在实际问题中,互斥锁可以解决大部分互斥的问题,保证资源可以被独占式使用,但是有时候互斥锁可能会导致效率降低。比如:系统中有成千上万条线程对同一资源进行访问,其中绝大部分是对其进行读取,只有少部分线程需要对其进行写入,这样使用互斥锁效率就会很低,所以使用读写锁。

读锁:获取数据( read、printf、fread、fget、get、getchar、scanf),当一个线程上了读锁,其他线程可以一直上读锁。

写锁:修改数据(write、puts、fwrite、fputs、putchar)当一个线程上了写锁,后面的其他线程读、写都不能上,直到解了第一个写锁。


二、读写锁对对应的API

1、初始化读写锁

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

attr:锁的属性一般设置为NULL

返回值:成功返回0,失败返回非0

静态初始化读写锁: pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;

代码段:

 pthread_rwlock_t rwl;
 int pthread_rwlock_init_ret = pthread_rwlock_init(&rwl, NULL);
   if (pthread_rwlock_init_ret != 0)
   {
       perror("pthread_rwlock_init");
       exit(-1);
   }
   else
   {
       printf("读写锁初始化成功!\n");
   }

2、读锁、写锁、销毁读写锁

读锁:int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);

写锁:int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);

销毁读写锁:int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

代码段:验证上了写锁后只有在解了写锁才能再上读锁

#include <stdio.h>
#include <errno.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
pthread_rwlock_t rwl;
void *Pthread_Task(void *arg)
{
    if ((long)arg == 1)
    {
        printf("我是第%ld号线程,我要上写锁\n", (long)arg);
        int pthread_rwlock_rdlock_ret = pthread_rwlock_wrlock(&rwl);
        if (pthread_rwlock_rdlock_ret != 0)
        {
            perror("pthread_rwlock_rdlock");
            exit(-1);
        }
        else
        {
            printf("我是%ld号线程,我上写锁成功!3s之后我解写锁\n", (long)arg);
            sleep(3);
            int pthread_rwlock_unlock_ret = pthread_rwlock_unlock(&rwl);
            if(pthread_rwlock_unlock_ret != 0)
            {
                perror("pthread_rwlock_unlock");
                exit(-1);
            }
            else
            {
                printf("解写锁成功!\n");
            }
        }
    }
    if ((long)arg == 2)
    {
        printf("我是第%ld号线程,我要上读锁\n", (long)arg);
        int pthread_rwlock_rdlock_ret = pthread_rwlock_rdlock(&rwl);
        if (pthread_rwlock_rdlock_ret != 0)
        {
            perror("pthread_rwlock_rdlock");
            exit(-1);
        }
        else
        {
            printf("我是%ld号线程,我上读锁成功!\n", (long)arg);
        }
    }
    pthread_exit(NULL);
}

int main()
{
    int pthread_rwlock_init_ret = pthread_rwlock_init(&rwl, NULL);
    if (pthread_rwlock_init_ret != 0)
    {
        perror("pthread_rwlock_init");
        exit(-1);
    }
    else
    {
        printf("读写锁初始化成功!\n");
    }
    pthread_t pid1, pid2;
    pthread_create(&pid1, NULL, Pthread_Task, (void *)1);
    sleep(1);
    pthread_create(&pid2, NULL, Pthread_Task, (void *)2);
    pause();
}


代码实现效果:

相关文章
|
8天前
|
安全 算法 Linux
【Linux】线程安全——补充|互斥、锁|同步、条件变量(下)
【Linux】线程安全——补充|互斥、锁|同步、条件变量(下)
18 0
|
8天前
|
存储 安全 Linux
【Linux】线程安全——补充|互斥、锁|同步、条件变量(上)
【Linux】线程安全——补充|互斥、锁|同步、条件变量(上)
14 0
|
8天前
|
缓存 Linux 编译器
【Linux】多线程——线程概念|进程VS线程|线程控制(下)
【Linux】多线程——线程概念|进程VS线程|线程控制(下)
19 0
|
8天前
|
存储 Linux 调度
【Linux】多线程——线程概念|进程VS线程|线程控制(上)
【Linux】多线程——线程概念|进程VS线程|线程控制(上)
25 0
|
15天前
|
Java Linux Shell
Linux软件安装和部署Java代码
Linux软件安装和部署Java代码
21 0
|
24天前
|
安全 Linux 数据安全/隐私保护
【linux】线程同步和生产消费者模型
【linux】线程同步和生产消费者模型
15 0
|
25天前
|
Java
java线程之读写锁
java线程之读写锁
15 0
|
10天前
|
设计模式 安全 Java
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
27 1
|
10天前
|
设计模式 存储 安全
Java面试题:设计一个线程安全的单例类并解释其内存占用情况?使用Java多线程工具类实现一个高效的线程池,并解释其背后的原理。结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
Java面试题:设计一个线程安全的单例类并解释其内存占用情况?使用Java多线程工具类实现一个高效的线程池,并解释其背后的原理。结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
21 1
|
10天前
|
设计模式 并行计算 安全
Java面试题:如何使用设计模式优化多线程环境下的资源管理?Java内存模型与并发工具类的协同工作,描述ForkJoinPool的工作机制,并解释其在并行计算中的优势。如何根据任务特性调整线程池参数
Java面试题:如何使用设计模式优化多线程环境下的资源管理?Java内存模型与并发工具类的协同工作,描述ForkJoinPool的工作机制,并解释其在并行计算中的优势。如何根据任务特性调整线程池参数
13 0