Linux线程安全(二)条件变量实现线程同步

目录

条件变量

条件变量初始化和唤醒

键盘触发条件变量唤醒线程demo

条件变量的等待

条件变量定时等待demo

条线变量实现多线程间的同步


条件变量

条件变量是为了控制多个线程的同步工作而设计的

比如说一个系统中有多个线程的存在但有且仅有一个线程在工作,我们需要等待这个线程执行完任务之后然后唤醒另一个线程执行另外一个任务,

那这个时候"正在工作的这个线程执行完任务"就是一个条件变量,等这个条件变量触发之后正在工作的线程就会休眠,然后新的线程会启动。

条件变量初始化和唤醒

#include <pthread.h>

//销毁条件变量 int pthread_cond_destroy(pthread_cond_t *cond);

//初始化条件变量
int pthread_cond_init(pthread_cond_t *restrict cond,
const pthread_condattr_t *restrict attr);

cond:条件变量

attr:属性默认为 NULL

返回值: 成功 0 失败 -1

#include <pthread.h>

//随机唤醒一个等待的线程 int pthread_cond_signal(pthread_cond_t *cond);

//唤醒所有正在等待的线程 int pthread_cond_broadcast(pthread_cond_t *cond);

键盘触发条件变量唤醒线程demo
cpp 复制代码
#include <stdio.h>
#include <pthread.h>

pthread_cond_t cond;
pthread_mutex_t mutex;

int n = 0;

void *task(void *arg)
{
    while (1)
    {
        printf("%ld 线程等待条件\n", pthread_self());
        pthread_cond_wait(&cond, &mutex);
        if (n == 1)
        {
            n = 0;
            printf("%ld 线程被唤醒,执行任务\n", pthread_self());
        }
    }
}

int main()
{
    // 初始化锁与条件变量
    pthread_cond_init(&cond, NULL);
    pthread_mutex_init(&mutex, NULL);

    // 创建一个线程
    pthread_t tid;
    pthread_create(&tid, NULL, task, NULL);
    pthread_create(&tid, NULL, task, NULL);
    pthread_create(&tid, NULL, task, NULL);
    pthread_create(&tid, NULL, task, NULL);

    while (1)
    {
        printf("1.唤醒随机一个线程  2.唤醒所有线程\n");
        int n = 0;
        scanf("%d", &n);

        if (n == 1)
        {
            pthread_cond_signal(&cond); // 唤醒随机一个
        }
        else if (n == 2)
        {
            pthread_cond_broadcast(&cond); // 唤醒所有
        }
    }
}
条件变量的等待

#include <pthread.h>

//定时等待
int pthread_cond_timedwait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex,
const struct timespec *restrict abstime);

//一直等待
int pthread_cond_wait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex);

cond:条件变量

mutex:互斥锁

abstime:定时器

返回值:

条件变量定时等待demo
cpp 复制代码
#include <stdio.h>
#include <pthread.h>
#include <time.h>

pthread_cond_t cond;

void *task(void *arg)
{
    while (1)
    {
        printf("输入任意键唤醒线程\n");
        getchar();
        pthread_cond_signal(&cond);
    }
}

int main()
{
    // 0.初始化互斥锁
    pthread_mutex_t mutex;
    pthread_mutex_init(&mutex, NULL);

    // 1.初始化条件变量
    int ret = pthread_cond_init(&cond, NULL);
    if (ret < 0)
    {
        perror("初始化条件变量失败\n");
    }

    // 创建一个线程
    pthread_t tid;
    pthread_create(&tid, NULL, task, NULL);

    // 2.开启定时等待
    while (1)
    {
        // 设置时间
        struct timespec ts;

        //clock_gettime()获取时间函数
        //CLOCK_REALTIME:系统实时时间,可以从网络同步,也可以用户自行更改
        clock_gettime(CLOCK_REALTIME, &ts); 

#if 0  //timespec结构体,tv_sec为秒
struct timespec
{
  __time_t tv_sec;    /* Seconds.  秒*/
  __syscall_slong_t tv_nsec;  /* Nanoseconds.纳秒*/      
}           
#endif

        ts.tv_sec += 5;                     // 时间增加 5 秒
        printf("开启定时等待5秒\n");
        //pthread cond wait函数的返回值为0,代表成功等待条件变量并且收到了通知。
        //如果返回值是一个非零值,则表示函数运行出现了错误
        //需要根据错误码进行处理。
        int ret = pthread_cond_timedwait(&cond, &mutex, &ts);
        printf("等待结束 %d\n", ret);  //超时返回值110
    }
}

条线变量实现多线程间的同步

利用条件变量使三个线程轮流运作,线程1执行完之后执行线程2,线程2执行完之后执行线程3,线程3执行完之后重新执行线程1.

cpp 复制代码
#include <stdio.h>
#include <pthread.h>

// 定义三个条件
pthread_cond_t first;  // 条件1
pthread_cond_t second; // 条件2
pthread_cond_t third; // 条件3

pthread_mutex_t mutex;

void *task(void *arg)
{
    while (1)
    {
        pthread_cond_wait(&third, &mutex);
        printf("线程1运行\n");
        pthread_cond_signal(&first);
    }
}

void *task1(void *arg)
{
    while (1)
    {
        pthread_cond_wait(&first, &mutex);
        printf("线程2运行\n");
        pthread_cond_signal(&second);
    }
}

void *task2(void *arg)
{
    while (1)
    {
        pthread_cond_wait(&second, &mutex);
        printf("线程3运行\n");
        pthread_cond_signal(&third);
    }
}

int main()
{
    // 初始化条件变量与线程锁
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&first, NULL);
    pthread_cond_init(&second, NULL);
    pthread_cond_init(&third, NULL);

    // 创建三个任务线程
    pthread_t tid;
    pthread_create(&tid, NULL, task, NULL);
    pthread_t tid1;
    pthread_create(&tid1, NULL, task1, NULL);
    pthread_t tid2;
    pthread_create(&tid2, NULL, task2, NULL);

    while (1)
    {
        printf("输入任意键线程开始工作\n");
        getchar();
        pthread_cond_signal(&third);
    }
}
相关推荐
qwy7152292581632 分钟前
13-R数据重塑
服务器·数据库·r语言
fai厅的秃头姐!2 小时前
C语言03
c语言·数据结构·算法
life_time_2 小时前
C语言(22)
c语言·开发语言
anddddoooo2 小时前
域内证书维权
服务器·网络·网络协议·安全·网络安全·https·ssl
zhoupenghui1683 小时前
golang时间相关函数总结
服务器·前端·golang·time
lllsure3 小时前
Linux 实用指令
linux·物联网
努力的小T3 小时前
使用 Docker 部署 Apache Spark 集群教程
linux·运维·服务器·docker·容器·spark·云计算
Nerd Nirvana4 小时前
OpenSSL crt & key (生成一套用于TLS双向认证的证书密钥)
linux·ssl·shell·认证·加密·tls·oepnssl
不修×蝙蝠4 小时前
HTTP 协议(Ⅲ)
服务器·http·javaee·http协议
letisgo54 小时前
记录一次部署PC端网址全过程
linux·阿里云·服务器运维