互斥锁和读写锁

因为一个进程中的所有线程共享进程的地址空间,所以要求对临界资源的访问要做到互斥和同步;使用互斥锁、读写锁可以实现线程间对临界资源访问时的互斥。

互斥锁

①初始化和销毁互斥锁

静态初始化互斥锁:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
动态初始化互斥锁:
int pthread_mutex_init(pthread_mutex_t *restrict mutex,constpthread_mutexattr_t *restrict attr);

销毁互斥锁:
int pthread_mutex_destroy(pthread_mutex_t *mutex);

②给互斥锁上锁和解锁

#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);
函数功能:给互斥锁上锁,上锁不成功就阻塞

#include <pthread.h>
int pthread_mutex_trylock(pthread_mutex_t *mutex);
函数功能:尝试给互斥锁上锁,若上锁不成功就立即结束调用此函数,不会阻塞

#include <pthread.h>
int pthread_mutex_unlock(pthread_mutex_t *mutex);
函数功能:对互斥锁解锁

test:创建两个线程,分别对临界资源访问,在访问时利用互斥锁实现互斥。

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

int a = 0;
pthread_mutex_t mutex;

void *thread1(void *arg)
{
    printf("thread1 start...\n");
    pthread_mutex_lock(&mutex); //线程1访问临界资源前,先把互斥锁上锁
    a = 10;
    pthread_mutex_unlock(&mutex);   //访问完临界资源,再把互斥锁解锁
    printf("thread1 end...\n");

    pthread_exit(NULL);
}

void *thread2(void *arg)
{
    printf("thread2 start...\n");
    pthread_mutex_lock(&mutex);	
    printf("a = %d\n", a);
    pthread_mutex_unlock(&mutex);
    printf("thread2 end...\n");

    pthread_exit(NULL);
}

int main(int argc, char const *argv[])
{
    pthread_t tid[2];
    pthread_create(&tid[0], NULL, thread1, NULL);
    pthread_create(&tid[1], NULL, thread2, NULL);

    pthread_join(tid[0], NULL);
    pthread_join(tid[1], NULL);

    return 0;
}

在这里插入图片描述
结果分析:thread2想要访问临界资源时,thread1已经持有这个互斥锁,所以thread2想要对这把共享互斥锁上锁时,就被阻塞,等待thread1释放锁才解除阻塞。

读写锁

pthread_rwlock_t读写锁有读锁和写锁两把锁,读锁和写锁是互斥的,即一个线程持有写锁对临界资源进行写操作时,不允许其他线程持有读锁对其读操作,反之亦然,但是多个线程可以同时持有读锁,同时进行读操作。

初始化互斥锁:

动态初始化:
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
atrr----->为NULL的话,默认初始化锁为读写锁
静态初始化:
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;

销毁互斥锁:

int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

给读写锁上写锁:

int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);

给读写锁上读锁:

int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);//其他线程持有写锁时,就调用失败并使得线程阻塞
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);//调用失败不会阻塞,失败就立即结束调用

test:一个线程对临界资源写操作,其他线程进行读操作

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

int a = 0;
pthread_rwlock_t rwlock;

void *thread1(void *arg)    //写线程
{
    for(int i = 0; i < 5; ++i)
    {
        pthread_rwlock_wrlock(&rwlock); //上写锁
        sleep(2);   //假设thread1对数据处理了2s
        a++;
        printf("thread1 write\n");
        pthread_rwlock_unlock(&rwlock); //释放锁

    }
}

void *thread2(void *arg)
{
    for(int i = 0; i < 5; ++i)
    {
        pthread_rwlock_rdlock(&rwlock); //上读锁
        printf("thread2 read: a = %d\n", a);
        pthread_rwlock_unlock(&rwlock); //释放锁
        sleep(1);
    }
}

void *thread3(void *arg)
{
    for(int i = 0; i < 5; ++i)
    {
        pthread_rwlock_rdlock(&rwlock); //上读锁
        printf("thread3 read: a = %d\n", a);
        pthread_rwlock_unlock(&rwlock); //释放锁
        sleep(1);
    }
}


int main(int argc, char const *argv[])
{
    pthread_rwlock_init(&rwlock, NULL);
    pthread_t tid[3];
    pthread_create(&tid[0], NULL, thread1, NULL);
    pthread_create(&tid[1], NULL, thread2, NULL);
    pthread_create(&tid[2], NULL, thread3, NULL);

    for(int i = 0; i < 3; ++i)
        pthread_join(tid[i], NULL);

    pthread_rwlock_destroy(&rwlock);

    return 0;
}

在这里插入图片描述
结果分析:在thread1持有写锁进行写操作的2s期间内,thread2和thread3企图对持有读锁临界资源读操作,但是读锁和写锁是互斥的,所以thread2和thread3被阻塞,当thread1释放写锁后,thread2和thread3同时持有读锁,对临界资源同时进行读操作,此时,thread1试图持有写锁,但是由于读锁和写锁的互斥性,此时的thread1也被阻塞。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值