条件变量解决同步问题之打印金鱼

说明

本代码为jyy老师上课演示条件变量解决同步问题示例(本人只做记录与分享)
本人未使用老师封装的POSIX线程库, 直接在单文件中调试并注释

问题描述

有三类线程
T1 若干: 死循环打印<
T2 若干: 死循环打印>
T3 若干: 死循环打印_
任务:
对线程同步,使得屏幕打印出<><__><>的组合

状态机

在这里插入图片描述

代码

#include <pthread.h>
#include <iostream>
#include <assert.h>
#include <string>
#include <vector>

#define Lock(x) pthread_mutex_lock(x) 
#define UnLock(x) pthread_mutex_unlock(x)

// 状态机的状态, 从1开始编号
enum { A = 1, B, C, D, E, F, };
// 构建状态机的
struct rule {
  int from, ch, to;
};
std::vector<rule> rules = {
    // <><
    {A, '<', B},
    {B, '>', C},
    {C, '<', D},
    // ><>
    {A, '>', E},
    {E, '<', F},
    {F, '>', D},
    // D是打印出一条鱼后停留的状态, 
    // 需要经过'_'到初始状态A, 重新打印鱼
    {D, '_', A},
};
// 当前状态
int current_state = A;

pthread_mutex_t lk = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cv = PTHREAD_COND_INITIALIZER;

/**
 * 检查当前状态是否又ch这条出边
 * 返回0表示无法根据ch转移到一个状态
*/
int next(char ch) {
    // 检查ch是否是当前状态的出边
    for (const auto& rule : rules) {
        if (rule.from == current_state && rule.ch == ch) {
            return rule.to;
        }
    }
    return 0;
}
/**
 * 检查同步条件是否满足
*/
static int can_print(char ch) {
    return next(ch) != 0;
}
// 创建12个线程, 每4个打印同种字符
std::string charlib = ".<<<<<>>>>___";

void* fish_thread(void* arg) {
    int id = *((int *)arg);
    char role = charlib[id];
    while (true) {
        // 先上锁
        Lock(&lk);
        // 再检查条件变量
        while (!can_print(role)) {
            pthread_cond_wait(&cv, &lk);
        }
        putchar(role); // Not lock-protected
        // 更新到下一个状态
        current_state = next(role);
        assert(current_state);
        // 更新状态后可能会使得等待该条件的线程满足条件
        pthread_cond_broadcast(&cv);
        UnLock(&lk);
    }
}

int main() {
    std::vector<pthread_t> threads(charlib.size());
    std::vector<int> pid(charlib.size());
    for (int i = 0; i < charlib.size(); i++) {
        pid[i] = i + 1;
        pthread_create(&threads[i], nullptr, &fish_thread, &pid[i]);
    }
    for (int i = 0; i < charlib.size(); i++) {
        pthread_join(threads[i], nullptr);
    }
}

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值