当前位置: 首页 > article >正文

Webserver(3.2)锁

目录

  • 互斥量
  • 死锁
    • 未解锁
    • 重复加锁
    • 多个锁
  • 读写锁
    • 案例

互斥量

接上一章,卖票存在线程安全问题。

#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
int tickets=1000;//局部变量就是每个人卖100张,全局变量就是一起卖100张,所有线程共享一份资源
//创建一个互斥量
pthread_mutex_t mutex;
void * sellticket(void * arg){

    
    //卖票
    while(1){
        //加锁
        pthread_mutex_lock(&mutex);
        if(tickets>0){
            usleep(3000);
            printf("%ld 正在卖第 %d 张门票\n",pthread_self(),tickets);
            tickets--;
        }else{
            //解锁
            pthread_mutex_unlock(&mutex);
            break;
        }
        //解锁
        pthread_mutex_unlock(&mutex);

    }

    
    return NULL;
}
int main(){

    //初始化互斥量
    pthread_mutex_init(&mutex,NULL);

    //创建3个子线程
    pthread_t tid1,tid2,tid3;
    pthread_create(&tid1,NULL,sellticket,NULL);
    pthread_create(&tid2,NULL,sellticket,NULL);
    pthread_create(&tid3,NULL,sellticket,NULL);

    //回收子线程的资源,阻塞
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
    pthread_join(tid3,NULL);

   
    pthread_exit(NULL);//退出主线程


    //释放互斥量资源
    pthread_mutex_destroy(&mutex);


    return 0;
}

不同的线程卖出几十张之后,切换到另一个线程来卖
在这里插入图片描述
虽然解决了数据安全的问题,但效率降低了,变成串行

死锁

未解锁

#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
int tickets=1000;//局部变量就是每个人卖100张,全局变量就是一起卖100张,所有线程共享一份资源
//创建一个互斥量
pthread_mutex_t mutex;
void * sellticket(void * arg){

    
    //卖票
    while(1){
        //加锁
        pthread_mutex_lock(&mutex);
        if(tickets>0){
            usleep(3000);
            printf("%ld 正在卖第 %d 张门票\n",pthread_self(),tickets);
            tickets--;
        }else{
            //解锁
            pthread_mutex_unlock(&mutex);
            break;
        }
        //解锁
        //pthread_mutex_unlock(&mutex);

    }

    
    return NULL;
}
int main(){

    //初始化互斥量
    pthread_mutex_init(&mutex,NULL);

    //创建3个子线程
    pthread_t tid1,tid2,tid3;
    pthread_create(&tid1,NULL,sellticket,NULL);
    pthread_create(&tid2,NULL,sellticket,NULL);
    pthread_create(&tid3,NULL,sellticket,NULL);

    //回收子线程的资源,阻塞
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
    pthread_join(tid3,NULL);

   
    pthread_exit(NULL);//退出主线程


    //释放互斥量资源
    pthread_mutex_destroy(&mutex);


    return 0;
}

未解锁会无法切换线程

在这里插入图片描述

重复加锁

#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
int tickets=1000;//局部变量就是每个人卖100张,全局变量就是一起卖100张,所有线程共享一份资源
//创建一个互斥量
pthread_mutex_t mutex;
void * sellticket(void * arg){

    
    //卖票
    while(1){
        //加锁
        pthread_mutex_lock(&mutex);
        pthread_mutex_lock(&mutex);
        if(tickets>0){
            usleep(3000);
            printf("%ld 正在卖第 %d 张门票\n",pthread_self(),tickets);
            tickets--;
        }else{
            //解锁
            pthread_mutex_unlock(&mutex);
            break;
        }
        //解锁
        pthread_mutex_unlock(&mutex);

    }

    
    return NULL;
}
int main(){

    //初始化互斥量
    pthread_mutex_init(&mutex,NULL);

    //创建3个子线程
    pthread_t tid1,tid2,tid3;
    pthread_create(&tid1,NULL,sellticket,NULL);
    pthread_create(&tid2,NULL,sellticket,NULL);
    pthread_create(&tid3,NULL,sellticket,NULL);

    //回收子线程的资源,阻塞
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
    pthread_join(tid3,NULL);

   
    pthread_exit(NULL);//退出主线程


    //释放互斥量资源
    pthread_mutex_destroy(&mutex);


    return 0;
}

也会无法执行
在这里插入图片描述

多个锁

多线程对多个锁进行操作时

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

//创建两个互斥量
pthread_mutex_t mutex1,mutex2;

void * workA(void * arg){

    pthread_mutex_lock(&mutex1);
    sleep(1);
    pthread_mutex_lock(&mutex2);

    printf("workA...\n");

    pthread_mutex_unlock(&mutex2);
    pthread_mutex_unlock(&mutex1);

    return NULL;
}

void * workB(void * arg){
    pthread_mutex_lock(&mutex2);
    sleep(1);
    pthread_mutex_lock(&mutex1);

    printf("workB...\n");

    pthread_mutex_unlock(&mutex1);
    pthread_mutex_unlock(&mutex2);
    return NULL;
}


int main(){

    //初始化互斥量
    pthread_mutex_init(&mutex1,NULL);
    pthread_mutex_init(&mutex2,NULL);

    //创建2个子线程
    pthread_t tid1,tid2;
    pthread_create(&tid1,NULL,workA,NULL);
    pthread_create(&tid2,NULL,workB,NULL);

    //回收子线程资源
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);


    //释放互斥量资源
    pthread_mutex_destroy(&mutex1);
    pthread_mutex_destroy(&mutex2);
    


    return 0;
}

在这里插入图片描述

读写锁

同时去读共享资源没有问题,但是互斥锁的排他性太强了,读没有影响,互斥锁读都不行

案例

8个线程操作同一个全局变量
3个线程不定时写一个全局变量,其余5个线程不定时的读一个全局变量

#define _XOPEN_SOURCE 500
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>


//创建一个共享数据
int num=1;
pthread_rwlock_t rwlock;

void * writeNum(void * arg){
    while(1){
        pthread_rwlock_wrlock(&rwlock);
        num++;
        printf("++write,tid:%ld,num:%d\n",pthread_self(),num);
        pthread_rwlock_unlock(&rwlock);
        usleep(100);
    }
    return NULL;
}

void * readNum(void * arg){
    while(1){
        pthread_rwlock_rdlock(&rwlock);
        printf("==read,tid:%ld,num:%d\n",pthread_self(),num);
        pthread_rwlock_unlock(&rwlock);
        usleep(100);
    }
    return NULL;
}

int main(){

    pthread_rwlock_init(&rwlock,NULL);

    //创建3个写线程,5个读线程
    pthread_t wtids[3],rtids[5];
    for(int i=0;i<3;i++){
        pthread_create(&wtids[i],NULL,writeNum,NULL);
    }

    for(int i=0;i<5;i++){
        pthread_create(&rtids[i],NULL,readNum,NULL);
    }

    //设置线程分离
    for(int i=0;i<3;i++){
        pthread_detach(wtids[i]);
    }

    for(int i=0;i<5;i++){
        pthread_detach(rtids[i]);
    }

    //主线程退出
    pthread_exit(NULL);

    pthread_rwlock_destroy(&rwlock);
    return 0;
}

在这里插入图片描述


http://www.kler.cn/a/381886.html

相关文章:

  • 单片机:实现数码管动态显示(0~99999999)74hc138驱动(附带源码)
  • VS2022 中的 /MT /MTd /MD /MDd 选项
  • 详解磁盘IO、网络IO、零拷贝IO、BIO、NIO、AIO、IO多路复用(select、poll、epoll)
  • 贪心算法(三)
  • |-牛式-|
  • 内网穿透ubuntu20 docker coplar
  • 基于CentOS 7.9上安装WebLogic
  • 【STL_list 模拟】——打造属于自己的高效链表容器
  • EasyExcel 学习之 导出 “文件编码问题”
  • 苍穹外卖 商家取消、派送、完成订单
  • HTB:PermX[WriteUP]
  • 附件商户,用户签到,uv统计功能(geo,bitmap,hyperloglog结构的使用)
  • 如何使用RabbitMQ和Python实现广播消息
  • 深度学习基础知识-Batch Normalization(BN)超详细解析
  • 第二节 管道符、重定向与环境变量
  • 手写一个axios方法
  • python爬取旅游攻略(1)
  • SparkSql读取数据的方式
  • 多模态PaliGemma——Google推出的基于SigLIP和Gemma的视觉语言模型
  • 十四届蓝桥杯STEMA考试Python真题试卷第二套第四题
  • (八)JavaWeb后端开发——Tomcat
  • 使用GitHub Actions实现CI/CD流程
  • JavaScript数据类型- Symbol 详解
  • 各种网络设备的工作原理
  • Hive SQL中判断内容包含情况的全面指南
  • MR30分布式IO模块与高效PLC协同