【C语言_线程pthread_互斥锁mutex_条件触发cond 之解析与示例 (开源)】.md updata:23/11/03

文章目录

      • [线程 pthread](#线程 pthread)
        • [线程 vs 进程](#线程 vs 进程)
        • [线程退出 等待 消息传递](#线程退出 等待 消息传递)
          • [join:等待,传参void*; exit:退出,对参数赋值void**;](#join:等待,传参void*; exit:退出,对参数赋值void**;)
        • [互斥锁 mutex](#互斥锁 mutex)
          • [互斥锁mutex+条件cond_等待wait、触发signal 控制线程执行](#互斥锁mutex+条件cond_等待wait、触发signal 控制线程执行)
        • [补充: 宏-静态初始化 互斥锁/条件](#补充: 宏-静态初始化 互斥锁/条件)

线程 pthread

线程 vs 进程

线程:直接用主程序的内存地址,所以如果在线程里改主程序变量,就是直接改;

线程vs进程:

a.比进程快大概30倍,不需要复制完全一样的内存来创建运行,直接使用主程序的内存;

b.没有进程那么健壮,子线程蹦了,就都崩了;

而对进程而言,子进程崩了,父进程不受影响继续执行;

线程退出 等待 消息传递
join:等待,传参void*; exit:退出,对参数赋值void**;
javascript 复制代码
#include <stdio.h>
#include <pthread.h>
#include <string.h>

//创建线程
//int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
// 返回:若成功返回0,否则返回错误编号

//子线程执行函数func1里的pthread_exit负责将void* 传递给主线程的pthread_joi的void **参数;
//int pthread_exit(void *rval_ptr);

// int pthread_join(pthread_t thread, void **rval_ptr);
// 返回:若成功返回0,否则返回错误编号

void *func1(void * arg)
{
    static char data[] = "I am ok! thanks!";
    printf("t1 id:%d\n",(int)pthread_self());
    printf("t1 arg data:%s\n",(char* )arg);
    pthread_exit((void* )data);
}

int main()
{
    pthread_t t1;
    char arg[] = "Are you ok?";
    char data1[1024];
    memset(data1,'\0',sizeof(data1));

    printf("main id:%d\n",(int)pthread_self());
    int creatN = pthread_create(&t1,NULL,func1, (void*)arg); 
    //创建其他线程,也是类似操作: 定义好执行函数func2,和传入的形参arg2即可;
    //pthread_create(&t2,NULL,func2, (void*)arg2); 

    void* ret;
    pthread_join(t1,&ret);
    strcpy(data1, (char*)ret);
    printf("t1 return data:%s\n",data1);
    return 0;
}
互斥锁 mutex

互斥锁:我上锁,你就不能用了,除非我解锁了,你才能用;

配合线程使用;

互斥锁mutex+条件cond_等待wait、触发signal 控制线程执行

//例:

javascript 复制代码
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>

/*-----------------------------------------------------*/
// 创建互斥锁变量 
//pthread_mutex_t 锁名
// 初始化及销毁互斥锁
// int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
// int pthread_mutex_destroy(pthread_mutex_t mutex);
// 返回:若成功返回0,否则返回错误编号

//上锁 例:pthread_mutex_lock(&mutex);
//解锁 例:pthread_mutex_unlock(&mutex);

/*-----------------------------------------------------*/

// 创建条件变量 
//pthread_cond_t 条件名
// 初始化及销毁条件变量
// int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr); //消息只给一个线程
// int pthread_cond_destroy(pthread_cond_t *cond);  //广播给所有线程
// 返回:若成功返回0,否则返回错误编号

// 等待
// int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
// int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, cond struct timespec *restrict timeout);
// 返回:若成功返回0,否则返回错误编号

//触发
// int pthread_cond_signal(pthread_cond_t *cond);
// int pthread_cond_broadcast(pthread_cond_t *cond);
// 返回:若成功返回0,否则返回错误编号

/*-----------------------------------------------------*/

int numNB = 0;
pthread_mutex_t mutex;
pthread_cond_t cond;

void *func1(void * arg)
{
    printf("t1 id:%ld\n",(unsigned long)pthread_self());
    printf("t1 get main data:%s\n",(char* )arg);
    
    while(1){
        pthread_cond_wait(&cond,&mutex);
        printf("--------------------\n");
        printf("t1:%d\n",numNB++);
        printf("--------------------\n");
        sleep(1);
        numNB = 0;
    }

}

void *func2(void * arg)
{
    printf("t2 id:%ld\n",(unsigned long)pthread_self());
    printf("t2 get main data:%s\n",(char* )arg);
    while(1){
        pthread_mutex_lock(&mutex);                
        printf("t2:%d\n",numNB++);
        pthread_mutex_unlock(&mutex);
        
        if(numNB == 3){
           pthread_cond_signal(&cond); 
        }     
        sleep(1);   
    } 
}

int main()
{
    pthread_mutex_init(&mutex,NULL);
    pthread_cond_init(&cond,NULL);
    pthread_t t1,t2;
    void* ret;
    char arg[] = "Are you ok?";
    char data1[1024];
    memset(data1,'\0',sizeof(data1));
    
    int creatN1 = pthread_create(&t1,NULL,func1, (void*)arg);
    int creatN2 = pthread_create(&t2,NULL,func2, (void*)arg);
    
    printf("main id:%ld\n",(unsigned long)pthread_self());

    pthread_join(t1,&ret);
    pthread_join(t2,&ret);
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);

    return 0;
}
补充: 宏-静态初始化 互斥锁/条件
javascript{.line-numbers} 复制代码
//在main函数里,不用宏,pthread_mutex_init() 正常初始化锁/条件的,即为动态初始化
//例:
pthread_mutex_t mutex;
int main()
{
    pthread_mutex_init(&mutex,NULL);
    return 0;
}

//在定义互斥锁/条件变量时,使用默认宏直接完成初始化,即为静态初始化
//例:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
相关推荐
说私域12 小时前
开源AI智能名片链动2+1模式S2B2C商城系统下消费点评的信任构建机制研究
人工智能·开源
福大大架构师每日一题12 小时前
⽬前 主流的开源模型体系 有哪些?
chatgpt·开源
万岳科技系统开发12 小时前
外卖开源系统源码设计思路:商家、骑手、用户三端一体化方案
开源
ACP广源盛1392462567313 小时前
(ACP广源盛)GSV2231---DisplayPort 1.4 MST 到 HDMI 2.0/DP/Type-C 转换器(带嵌入式 MCU)
c语言·开发语言·单片机·嵌入式硬件·音视频·mst
QT 小鲜肉13 小时前
【QT/C++】Qt网络编程进阶:UDP通信和HTTP请求的基本原理和实际应用(超详细)
c语言·网络·c++·笔记·qt·http·udp
Yurko1313 小时前
【C语言】选择结构和循环结构的进阶
c语言·开发语言·学习
那些免费的砖14 小时前
Reka UI - 一款免费开源的 Vue 无头 UI 组件库,样式定制开发项目的绝佳选择
vue.js·ui·开源
范纹杉想快点毕业14 小时前
12个月嵌入式进阶计划ZYNQ 系列芯片嵌入式与硬件系统知识学习全计划(基于国内视频资源)
c语言·arm开发·单片机·嵌入式硬件·学习·fpga开发·音视频
DolphinScheduler社区14 小时前
Apache DolphinScheduler 3.3.2 正式发布!性能与稳定性有重要更新
大数据·开源·apache·任务调度·海豚调度·发版
SeaTunnel14 小时前
Apache SeaTunnel 支持 Metalake 开发了!避免任务配置敏感信息暴露
大数据·开源·apache·个人开发·数据集成·seatunnel·看开源之夏