LeetCode 1114 按序打印

这篇博客深入探讨了在多线程环境中如何使用信号量(semaphore)和条件变量(condition variable)来实现线程间的同步和顺序控制。通过具体的代码示例展示了如何保证在并发情况下正确地交替打印'first', 'second', 'third',以及实现'FooBar'交替打印问题的解决方案。此外,还提到了基于信号量的生产者消费者模型,展示了如何利用互斥锁(mutex)和条件变量在Linux下实现这一模型。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

需求

在多线程环境下按序打印firstsecondthird,并且保证打印顺序不会出错

使用信号量

#include<semaphore.h>
class Foo {
    sem_t sem1;
    sem_t sem2;

public:
    Foo(){  //sem_init  初始化信号量
        //对信号量进行初始化;
        sem_init(&sem1,0,0);sem_init(&sem2,0,0);
    }

    void first(function<void()> printFirst) {
        
        // printFirst() outputs "first". Do not change or remove this line.
        printFirst();
        sem_post(&sem1);    //p操作,对信号量进行+1;
    }

    void second(function<void()> printSecond) {
        sem_wait(&sem1);    //对sem1进行v操作减一;
        // printSecond() outputs "second". Do not change or remove this line.
        printSecond();
        sem_post(&sem2);   //+1
    }

    void third(function<void()> printThird) {
        sem_wait(&sem2);   //减一;
        // printThird() outputs "third". Do not change or remove this line.
        printThird();
    }
};

条件变量+mutex+lock_Guard

class Foo {
    bool firstT;
    bool secondT;
    mutex mtx;
    condition_variable cv1,cv2;

public:
    Foo() {
         firstT=false,secondT=false   ;
    }

    void first(function<void()> printFirst) {
        lock_guard<mutex>  lg(mtx);    //对mtx初始化,作用域结束自动释放
        printFirst();
        firstT=true;
        cv1.notify_one();   //条件变量随机唤醒一个线程;
    }

    void second(function<void()> printSecond) {
        unique_lock<mutex> ul(mtx);    //加锁

        //只有表达式为false的时候会阻塞线程,为true的时候会唤醒线程;
        cv1.wait(ul,[&]{ return this->firstT;});   //lambda表达式
        
        printSecond();
        secondT=true;
        cv2.notify_one();   //唤醒一个线程;
    }

    void third(function<void()> printThird) {
        unique_lock<mutex> ul(mtx);
        cv2.wait(ul,[&]{ return this->secondT; });

        printThird();
    }
};

1115 交替打印FooBar

两个不同的线程将会共用一个 FooBar 实例。其中一个线程将会调用 foo() 方法,另一个线程将会调用 bar() 方法。
请设计修改程序,以确保 “foobar” 被输出 n 次。

条件变量 + unique_lock

class FooBar {
private:
    int n;
    mutex mtx;
    condition_variable cv;
    bool foo_down;
public:
    FooBar(int n) {
        this->n = n;
        foo_down=false;
    }

    void foo(function<void()> printFoo) {
        
        for (int i = 0; i < n; i++) {
            unique_lock<mutex> lock(mtx);
            cv.wait(lock,[&](){return !foo_down;});   //这是个lambda表达式;
        	// printFoo() outputs "foo". Do not change or remove this line.
        	printFoo();
            foo_down=true;
            cv.notify_one();
        }
    }

    void bar(function<void()> printBar) {
        
        for (int i = 0; i < n; i++) {
            unique_lock<mutex> lock(mtx);
            cv.wait(lock,[&](){return foo_down;});
        	// printBar() outputs "bar". Do not change or remove this line.
        	printBar();
            foo_down=false;
            cv.notify_one();
        }
    }
};

使用sem信号量

#include<semaphore.h>
class FooBar {
private:
    int n;
    sem_t sem1;
    sem_t sem2;
public:
    FooBar(int n) {
        this->n = n;
        sem_init(&sem1,0,0);
        sem_init(&sem2,0,1);   //最后一个值是设置value
    }

    void foo(function<void()> printFoo) {
        
        for (int i = 0; i < n; i++) {
            
        	// printFoo() outputs "foo". Do not change or remove this line.
            sem_wait(&sem2);
        	printFoo();
            sem_post(&sem1);
        }
    }

    void bar(function<void()> printBar) {
        
        for (int i = 0; i < n; i++) {
            sem_wait(&sem1);
        	// printBar() outputs "bar". Do not change or remove this line.
        	printBar();
            sem_post(&sem2);
        }
    }
};

linux下生产者消费者模型

#include<pthread.h>
class FooBar {
private:
    int n;
    pthread_mutex_t mutex;
    pthread_cond_t hasfoo,hasbar;
    bool foos;
public:
    FooBar(int n) {
        this->n = n;
        foos=false;
        pthread_mutex_init(&mutex,NULL);
        pthread_cond_init(&hasfoo,NULL);
        pthread_cond_init(&hasbar,NULL);
    }

    void foo(function<void()> printFoo) {
        
        for (int i = 0; i < n; i++) {
            pthread_mutex_lock(&mutex);
            while(foos)
            {
                pthread_cond_wait(&hasbar,&mutex);
            }
        	// printFoo() outputs "foo". Do not change or remove this line.
        	printFoo();
            foos=true;
            pthread_mutex_unlock(&mutex);
            pthread_cond_signal(&hasfoo);
        }
    }

    void bar(function<void()> printBar) {
        
        for (int i = 0; i < n; i++) {
            pthread_mutex_lock(&mutex);
            while(!foos)
            {
				pthread_cond_wait(&hasfoo,&mutex);
			}
        	// printBar() outputs "bar". Do not change or remove this line.
        	printBar();
            foos=false;
            pthread_mutex_unlock(&mutex);
            pthread_cond_signal(&hasbar);
        }
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值