leetcode 题:1117. H2O 生成(C++多线程编程)(困难)

7 篇文章 0 订阅

一、题目:1117. H2O 生成(难度:困难)

现在有两种线程,氢 oxygen 和氧 hydrogen,你的目标是组织这两种线程来产生水分子。

存在一个屏障(barrier)使得每个线程必须等候直到一个完整水分子能够被产生出来。

氢和氧线程会被分别给予 releaseHydrogen 和 releaseOxygen 方法来允许它们突破屏障。

这些线程应该三三成组突破屏障并能立即组合产生一个水分子。

你必须保证产生一个水分子所需线程的结合必须发生在下一个水分子产生之前。

换句话说:

如果一个氧线程到达屏障时没有氢线程到达,它必须等候直到两个氢线程到达。
如果一个氢线程到达屏障时没有其它线程到达,它必须等候直到一个氧线程和另一个氢线程到达。
书写满足这些限制条件的氢、氧线程同步代码。

 

示例 1:

输入: "HOH"
输出: "HHO"
解释: "HOH" 和 "OHH" 依然都是有效解。
示例 2:

输入: "OOHHHH"
输出: "HHOHHO"
解释: "HOHHHO", "OHHHHO", "HHOHOH", "HOHHOH", "OHHHOH", "HHOOHH", "HOHOHH" 和 "OHHOHH" 依然都是有效解。
 

限制条件:

输入字符串的总长将会是 3n, 1 ≤ n ≤ 50;
输入字符串中的 “H” 总数将会是 2n;
输入字符串中的 “O” 总数将会是 n。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/building-h2o
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

二、说明

由于对C++多线程不是很熟悉。使用了2个条件变量,3个互斥量,一个氢元素计数器countH1。思路就是,当count<2的时候,氢元素直接打印,count=2的时候出一个氧元素。count清0进入下一个循环。

1、当有氧元素线程进来的时候通过is_ready标志判断氢元素是否足够,如果不够使用一个条件变量和一个互斥量阻塞。

2、当有氢元素线程进来的时候,如果count<2,说明氢元素不足,直接进入下一步,并且count +1,如果count>=2说明氢元素已经足够了,在这里使用一个条件变量+一个互斥量阻塞。等待前一个水元素生成(2个H和1个O)之后被唤醒。

3、前面氢元素线程count<2的时候进入下一步,直接打印,同时判断如果count==2说明氢元素足够了,需要氧元素,这时候设置is_ready标识说明氢元素足够了,调用cv.notify_all();唤醒氧元素的线程,氧元素的线程发现is_ready == true之后,开始打印氧元素。(此时凑成2个H1个O)。同时将is_ready设为false,调用cv2.notify_all();唤醒被阻塞的氢元素线程,进入下一次原子合成。

虽然leecode accept了,但是感觉这样写貌似还有点漏洞,后面再补充补充。

三、代码

class H2O {
public:
    H2O() {
        countH1 = 0;
        is_ready = false;
    }
    std::mutex mtx;
    pthread_mutex_t work_mutex;
    bool is_ready;
    std::mutex mtx2;
    std::condition_variable cv2; 
    std::condition_variable cv; 
    int countH1;

    void hydrogen(function<void()> releaseHydrogen) { 
        // releaseHydrogen() outputs "H". Do not change or remove this line.
        while(countH1 >=2)
        {
                std::unique_lock <std::mutex> lck2(mtx2);
                 cv2.wait(lck2); 
        }
            pthread_mutex_lock(&work_mutex); 
            countH1 ++;
            //cout<<"countH1:"<<countH1<<endl;

            pthread_mutex_unlock(&work_mutex); 
             if(countH1 == 2)
             {
                 std::unique_lock <std::mutex> lck(mtx);
                 cv.notify_all(); 
                 is_ready = true;
             }
        //cout<<"out h:"<<countH1<<endl;
    //cout<<"H";
         releaseHydrogen();

    }

    void oxygen(function<void()> releaseOxygen) {
        
        // releaseOxygen() outputs "O". Do not change or remove this line.
  
            pthread_mutex_lock(&work_mutex);
    
           // cout<<"countO:"<<countO<<endl;
            pthread_mutex_unlock(&work_mutex);
            
        while(!is_ready)
        {
             std::unique_lock <std::mutex> lck(mtx);
             cv.wait(lck);
           // cout<<"await O,"<<"isready:"<<is_ready<<endl;
        }
            pthread_mutex_lock(&work_mutex);
            countH1 = 0;
            is_ready =false;
    
            //cout<<"out countO:"<<countO<<endl;
            //cout<<"O";
            pthread_mutex_unlock(&work_mutex);
        releaseOxygen();
        cv2.notify_all();
    }
};

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值