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;
}

原文地址:https://www.cnblogs.com/mangoczp/p/13542068.html