linux多线程之读写锁---rwlock

一:概述

  •   使用场景

对数据结构读的次数远大于写的情况。

  • 状态

 (1)读模式下加锁状态 (读锁)

 (2) 写模式下加锁状态 (写锁)

 (3) 不加锁状态

  •   遵循规则

          (1)读写锁是"写模式加锁"时, 解锁前,所有对该锁加锁的线程都会被阻塞。

          (2)读写锁是"读模式加锁"时, 如果线程以读模式对其加锁会成功;如果线程以写模式加锁会阻塞。

          (3)读写锁是没有读者,也没有写者,那么写者可以立刻获得读写锁,如果读写锁没有写者,那么读者可以立即获得该读写锁。

          (4)读锁、写锁并行阻塞,写锁优先级高,也叫共享-独占锁:写独占、读共享。

二:详细函数说明

  • 读写锁声明
pthread_rwlock_t  rwlock;
  • 初始化一个读写锁,相同的一个锁对象不能初始化两次
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
参数说明: 
rwlock —— 创建的读写锁 
attr —— 读写锁属性,NULL代表读写锁的各种属性取默认值。
返回值:初始化成功返回0;否则返回错误编号。
  • 销毁一个读写锁
int  pthread_rwlock_destroy( pthread_ rwlock_t  * rwlock );
参数说明: 
rwlock —— 需要销毁的的读写锁 
返回值:销毁成功返回0;否则返回错误编号。
  • 加锁
int  pthread_rwlock_rdlock ( pthread_ rwlock_t  * rwlock);//读模式加锁
int  pthread_rwlock_wrlock ( pthread_ rwlock_t  * rwlock);//写模式加锁
参数说明: 
rwlock—— 需要加锁的的读写锁 
返回值:加锁成功返回0;否则返回错误编号。

如果线程不希望被阻塞,可用调用如下函数进行尝试加锁,不可以获取锁时,这两个函数都返回EBUSY。

int  pthread_rwlock_tryrdlock( pthread_ rwlock_t  * rwlock);//读
int  pthread_rwlock_trywrlock( pthread_ rwlock_t  * rwlock);//写
参数说明: 
rwlock—— 需要尝试加锁的读写锁 
返回值:加锁成功返回0;否则返回EBUSY。

与互斥量一样,Single NUIX Specification 提供了带有超时的读写锁加锁函数,使应用程序在获取读写锁时避免陷入永久阻塞状态。当线程试图访问一个已经加锁的读写锁时,如下函数允许设定线程阻塞时间。这两个函数与pthread_ rwlock_rdlock()和pthread_ rwlock_wrlock()函数基本上是等价的,但是在达到超时时间值时不会对读写锁进行加锁,而是返回错误码ETIMEOUT。

int  pthread_rwlock_timedrdlock( pthread_ rwlock_t  *restrict  rwlock,
                               const struct timespec  *restrict  tsptr );
int  pthread_rwlock_timedwrlock( pthread_ rwlock_t  *restrict  rwlock,
                               const struct timespec  *restrict  tsptr );
参数说明: 
rwlock—— 需要加锁的读写锁 
tsptr —— 超时时间,线程愿意等待的绝对时间(与相对时间对比而言,指定在时间X之前可以等待,而不是愿意阻塞Y秒),用timespec结构来表示的(用秒和纳秒来描述时间)。 
返回值:加锁成功返回0;否则返回EBUSY。
  • 解锁

线程对读写锁访问结束,需要调用如下函数对读写锁进行解锁。下列行为均属于错误应该避免:对未加锁的信号量解锁,解锁其他线程锁定的读写锁。

int  pthread_rwlock_unlock( pthread_ rwlock_t  * rwlock);
参数说明: 
rwlock—— 需要解锁的读写锁 
返回值:解锁成功返回0;否则返回错误编号。

三:注意

  • 包含头文件:#include<pthread.h>
  • 由于pthread库不是Linux系统默认的库,连接时需要使用库libpthread,所以在编译中要加-lpthread参数eg:
gcc -o test1 -lpthread test1.c 

四:示例

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define COUNT_MAX 520
pthread_rwlock_t rwlock;
int m_Count=0;
void *pth_wr(void *arg)
{
    int i = (int)arg;
    while (m_Count <= COUNT_MAX)
    {
        pthread_rwlock_wrlock(&rwlock);//请求写锁
        printf("write================全局变量m_Count = %d, 我是%d号线程。\n", m_Count += 40, i + 1);
        pthread_rwlock_unlock(&rwlock);//解锁
        sleep(1);
    }
    return NULL;
}

void *pth_rd(void *arg)
{
    int i = (int)arg;
    while (m_Count <= COUNT_MAX)
    {
        pthread_rwlock_rdlock(&rwlock);//请求读锁
        printf("read=================全局变量m_Count = %d, 我是%d号线程。\n", m_Count, i + 1);
        pthread_rwlock_unlock(&rwlock);//解锁
        sleep(1);
    }
    return NULL;
}

int main(void)
{
    pthread_t pth[10];
    int i,j;
    pthread_rwlock_init(&rwlock, NULL);
    for (i = 0; i != 5; i++)//写
    {
        pthread_create(&pth[i], NULL, pth_wr, (void *)i);
    }
    for (i = 0; i != 5; i++)//读
    {
        pthread_create(&pth[5 + i], NULL, pth_rd, (void *)i);
    }
    while(1)
    {
        if (m_Count >= COUNT_MAX)
        {
            for (j = 0; j != 10; j++)
            {
                pthread_join(pth[j], NULL);//回收线程
            }
            break;
        }
    }
    return 0;
}
发布了34 篇原创文章 · 获赞 14 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/acliyu/article/details/86636658