• c++ 多线程 信号量简单使用


    完成一个多线程demo,保证三个线程执行顺序,即abc顺序打印
    代码示例:

    #include <iostream>
    #include <semaphore.h>
    #include <memory>
    #include <thread>
    using namespace std;
    
    sem_t firstJobDone; // c++ 线程如果执行成员函数会对this下的成员做一份拷贝,所以信号量不能作为 Foo 的成员变量。
    sem_t secondJobDone;
    class Foo : public std::enable_shared_from_this<Foo>{
    
    public:
        int v;
    public:
    
        Foo() {
            sem_init(&firstJobDone, 1, 0);
            sem_init(&secondJobDone, 1, 0);
        }
    
        void first() {
            cout<<'a'<<endl;
            sem_post(&firstJobDone);
            //sem_getvalue(&firstJobDone,&v);
            //cout<<"1done:"<<v<<"addr:"<<&firstJobDone<<endl;
        }
    
        void second() {
            //sleep(2);
            //sem_getvalue(&firstJobDone,&v);
            //cout<<"11done:"<<v<<"addr:"<<&firstJobDone<<endl;
            sem_wait(&firstJobDone);
            cout<<'b'<<endl;
            sem_post(&secondJobDone);
        }
    
        void third() {
            sem_wait(&secondJobDone);
            cout<<'c'<<endl;
        }
    
        std::shared_ptr<Foo> get_this(){
            return shared_from_this();
        }
    };
    
    int main(){
       auto foo_ptr = make_shared<Foo>();
    
       // std::thread t{[]{cout<<"xxx";}};
       std::thread t1{&Foo::first,*foo_ptr};
       std::thread t2{&Foo::second,*foo_ptr};
       std::thread t3{&Foo::third,*foo_ptr}; // c++ 获取成员函数指针的指定写法,并且需要传入this指针,因为成员函数第一个参数是this
       // std::thread t1{foo_ptr->first,*foo_ptr}; // error
       // std::thread t1{&(foo_ptr->first),*foo_ptr}; // error
       t1.join();
       t2.join();
       t3.join();
       return 0;
    }
    
    

    互斥量的使用可以用 mutex 库,lock/unlock,lock_guard(自动解锁,不可以手动lock/unlock),unique_lock(可以手动lock/unlock)

    给出 leetcode 1195 的解法:

    #include <semaphore.h>
    #include <functional>
    #include <thread>
    using namespace std;
    
    class FizzBuzz {
    private:
        int n;
        int cur;
        sem_t sem_fizz;
        sem_t sem_buzz;
        sem_t sem_fizz_buzz;
        sem_t sem_num;
    
    public:
        FizzBuzz(int n) {
            this->n = n;
            cur = 0;
            sem_init(&sem_fizz, 0, 0);
            sem_init(&sem_buzz, 0, 0);
            sem_init(&sem_fizz_buzz, 0, 0);
            sem_init(&sem_num, 0, 1);
        }
    
        // printFizz() outputs "fizz".
        void fizz(function<void()> printFizz) {
            while(cur <= n){
                sem_wait(&sem_fizz);
                if(cur > n) break;
                printFizz();
                sem_post(&sem_num);
            }
        }
    
        // printBuzz() outputs "buzz".
        void buzz(function<void()> printBuzz) {
            while(cur <= n){
                sem_wait(&sem_buzz);
                if(cur > n) break;
                printBuzz();
                sem_post(&sem_num);
            }
        }
    
        // printFizzBuzz() outputs "fizzbuzz".
        void fizzbuzz(function<void()> printFizzBuzz) {
            while(cur <= n){
                sem_wait(&sem_fizz_buzz);
                if(cur > n) break;
                printFizzBuzz();
                sem_post(&sem_num);
            }
        }
    
        // printNumber(x) outputs "x", where x is an integer.
        void number(function<void(int)> printNumber) {
            while(++cur <= n){
                sem_wait(&sem_num);
                if(cur % 3 == 0 && cur % 5 == 0){
                    sem_post(&sem_fizz_buzz);
                }else if(cur % 3 == 0){
                    sem_post(&sem_fizz);
                }else if(cur % 5 == 0){
                    sem_post(&sem_buzz);
                }else{
                    printNumber(cur);
                    sem_post(&sem_num);
                }
            }
    
            // 以下三个post通过更新sem_fizz等信号量,调动其他线程运行,进而结束所有线程
            sem_post(&sem_fizz);
            sem_post(&sem_buzz);
            sem_post(&sem_fizz_buzz);
        }
    };
    
    int main(int argc, char** argv){
        FizzBuzz fizzBuzz(15);
    
        std::function<void()> printFizz = [](){printf(" fizz ");};
        std::function<void()> printBuzz = [](){printf(" buzz ");};
        std::function<void()> printFizzBuzz = [](){printf(" fizzbuzz ");};
        std::function<void(int)> printNum = [](int x){printf(" %d ", x);};
    
        std::thread th[4];
        th[0] = std::thread(&FizzBuzz::fizz, &fizzBuzz, printFizz);
        th[1] = std::thread(&FizzBuzz::buzz, &fizzBuzz, printBuzz);
        th[2] = std::thread(&FizzBuzz::fizzbuzz, &fizzBuzz, printFizzBuzz);
        th[3] = std::thread(&FizzBuzz::number, &fizzBuzz, printNum);
    
        for(auto &ts : th) {
            if(ts.joinable()) ts.join();
        }
    
        return 0;
    }
    
    
  • 相关阅读:
    js 获取服务端时间,并实现时钟
    微信分享问题记录
    format
    vue-cli3 使用mint-ui
    vue.js 使用记录(1)
    iview admin 生成环境打包时路径问题
    java8:(Lambda 表达式简介)
    SpringBoot: 18.使用Scheduled 定时任务器(转)
    SpringBoot: 16.整合junit单元测试(转)
    SpringBoot: 17.热部署配置(转)
  • 原文地址:https://www.cnblogs.com/mangoczp/p/13542068.html
Copyright © 2020-2023  润新知