互斥锁,读写锁

    科技2024-10-18  22

    一、线程互斥方式。  ---  互斥锁 1、什么是互斥锁?特点怎么样? 互斥锁是专门用于处理线程之间互斥的一种方式,它有两种:上锁状态/解锁状态。 如果互斥锁处于上锁状态,那么再上锁就会阻塞,直到这把锁解开之后,才能上锁。 如果互斥锁处于解锁状态,那么再解锁依然可以的,不会阻塞。

    2、 互斥锁函数接口? 1)定义互斥锁变量   -> 数据类型: pthread_mutex_t    pthread_mutex_t m;

    2)初始化互斥锁。  -> pthread_mutex_init()  -> man 3 pthread_mutex_init 动态初始化: 头文件:     #include <pthread.h>

    原型:       int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);

    参数:     mutex:互斥锁变量的地址。     mutexattr:普通属性,填NULL。

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

    静态初始化: pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;    只要把该宏定义赋值给互斥锁变量,就等价于初始化了这把互斥锁。

    ======================== 也就是说: pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;

    等价于 pthread_mutex_t m; pthread_mutex_init(&m,NULL);

    3)上锁。  -> pthread_mutex_lock()  -> man 3 pthread_mutex_lock 头文件:     #include <pthread.h>

    原型:     int pthread_mutex_lock(pthread_mutex_t *mutex);

    参数:     mutex:互斥锁变量的地址。

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

    4)解锁。  -> pthread_mutex_unlock()  -> man 3 pthread_mutex_unlock 头文件:     #include <pthread.h>

    原型:     int pthread_mutex_unlock(pthread_mutex_t *mutex);

    参数:     mutex:互斥锁变量的地址。

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

    5)销毁互斥锁。   -> pthread_mutex_destroy()  -> man 3 pthread_mutex_destroy 头文件:     #include <pthread.h>

    原型:     int pthread_mutex_destroy(pthread_mutex_t *mutex);

    参数:     mutex:互斥锁变量的地址。

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

    一般地: 多个线程任务都一样的    -> 互斥锁 多个线程任务不一样的    -> 无名信号量

       练习1: 使用互斥锁完成5个线程打印helloworld。  -> 多个线程任务都一样的    练习2: 使用互斥锁完成<练习.docx>              -> 多个线程任务不一样的

    二、线程互斥方式。 --  读写锁 1、互斥锁有什么缺陷? 互斥锁无论是读取共享资源,还是修改共享资源,都要上锁,而且在上锁期间,不能被别的线程上锁。

    访问资源(一起读一本书)   -> 同时上读锁      -> 读锁就是一把共享锁。 修改资源(一起做一份试卷) -> 不能同时上写锁  -> 写锁就是一把互斥锁。

       这把既有读锁,又有写锁的锁,就称之为读写锁。

    2、读写锁函数接口? 1)定义一个读写锁变量。  数据类型: pthread_rwlock_t    pthread_rwlock_t rwlock;

    2)初始化读写锁?  -> pthread_rwlock_init()  -> man 3 pthread_rwlock_init 动态初始化: 头文件:     #include <pthread.h>

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

    参数:     rwlock: 读写锁的地址。     attr: 普通属性,填NULL。

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

    静态初始化: pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;

    3)读锁上锁。  -> pthread_rwlock_rdlock()   -> man 3 pthread_rwlock_rdlock 头文件:     #include <pthread.h>

    原型:     int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);

    参数:     rwlock: 读写锁的地址。

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

    4)写锁上锁。  -> pthread_rwlock_wrlock()   -> man 3 pthread_rwlock_wrlock 头文件:     #include <pthread.h> 原型:        int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);

    参数:     rwlock: 读写锁的地址。

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

    5)解锁。  -> pthread_rwlock_unlock()  -> man 3 pthread_rwlock_unlock 头文件:     #include <pthread.h>

    原型:        int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

    参数:     rwlock: 读写锁的地址。

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

    6)销毁读写锁。  -> pthread_rwlock_destroy()  -> man 3 pthread_rwlock_destroy 头文件:     #include <pthread.h> 原型:     int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

    参数:     rwlock: 读写锁的地址。

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

       练习3: 现有一个临界资源: "int a"  -> 全局变量        现在有4个线程,有两个线程想打印a的值   -> 读                         thread1: 3S   thread2:5S   -> 看时间 -> 如果读完需要8S,则读锁不能同时上

                 有两个线程想修改a的值,一个想改成30,一个想改成50   -> 写                         thread3: 4S   thread4: 6S     再开一条线程,用于倒数时间就行。

      验证:1)读锁可以同时上,写锁不可以同时上。     2)读锁与写锁能不能同时上?  -> 不可以,读锁要等到写锁解开了之后才能上锁。          #include "head.h"

    int a = 100; //临界资源 pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;

    void *func_time(void *arg) {     int i;     for(i=0;i<1000;i++)     {         printf("i = %d\n",i);         sleep(1);     } }

    //线程1: 打印a的值。 -> 3S (读操作) void *func1(void *arg) {     //1. 访问资源前,先上读锁。     pthread_rwlock_rdlock(&rwlock);     printf("thread 1 rdlock lock!\n");          //2. 打印a的值。     printf("a = %d\n",a);          //3. 持续3S     sleep(3);          //4. 访问完资源了,需要解锁。     pthread_rwlock_unlock(&rwlock);     printf("thread 1 rdlock unlock!\n");          //5. 线程退出     pthread_exit(NULL); }

    //线程2: 打印a的值。 -> 5S (读操作) void *func2(void *arg) {     //1. 访问资源前,先上读锁。     pthread_rwlock_rdlock(&rwlock);     printf("thread 2 rdlock lock!\n");          //2. 打印a的值。     printf("a = %d\n",a);          //3. 持续5S     sleep(5);          //4. 访问完资源了,需要解锁。     pthread_rwlock_unlock(&rwlock);     printf("thread 2 rdlock unlock!\n");          pthread_exit(NULL); }

    //线程3:修改a的值为50。   -> 4S void *func3(void *arg) {     //1. 修改资源之前,需要上写锁。     pthread_rwlock_wrlock(&rwlock);     printf("thread 3 wrlock lock!\n");          //2. 修改临界资源。     a = 50;          //3. 持续一段时间。     sleep(4);          //4. 修改资源后,需要解锁。     pthread_rwlock_unlock(&rwlock);     printf("thread 3 wrlock unlock!\n");          pthread_exit(NULL);      }

    //线程4:修改a的值为30。  -> 6S void *func4(void *arg) {     //1. 修改资源之前,需要上写锁。     pthread_rwlock_wrlock(&rwlock);     printf("thread 4 wrlock lock!\n");          //2. 修改临界资源。     a = 100;          //3. 持续一段时间。     sleep(6);          //4. 修改资源后,需要解锁。     pthread_rwlock_unlock(&rwlock);     printf("thread 4 wrlock unlock!\n");          pthread_exit(NULL); }

    int main(int argc,char *argv[]) {     //0.  创建一个用于倒数时间线程     pthread_t tid_time;     pthread_create(&tid_time,NULL,func_time,NULL);          //1、 创建2个子线程,用于打印临界资源的值。     pthread_t tid1,tid2,tid3,tid4;     pthread_create(&tid1,NULL,func1,NULL);     pthread_create(&tid2,NULL,func2,NULL);     pthread_create(&tid3,NULL,func3,NULL);     pthread_create(&tid4,NULL,func4,NULL);          //2.  接合线程     pthread_join(tid1,NULL);     pthread_join(tid2,NULL);     pthread_join(tid3,NULL);     pthread_join(tid4,NULL);          //3. 销毁读写锁     pthread_rwlock_destroy(&rwlock);          return 0; }

     

    Processed: 0.018, SQL: 8