天天看点

leetcode-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 。
           
typedef struct {
    sem_t H;
    sem_t O;
    int HCount; //H元素的计数
}H2O;

H2O* h2oCreate() {
    H2O* obj = (H2O*) malloc(sizeof(H2O));
    
    // Initialize user defined data here.
    if(sem_init(&obj->H, 0,2) < 0)
    {
        perror("sem_init");
        return NULL;
    }
    if(sem_init(&obj->O, 0,0) < 0)
    {
        perror("sem_init");
        return NULL;
    }
    obj->HCount = 0;
    return obj;
}

void hydrogen(H2O* obj) {
    sem_wait(&obj->H);
    // releaseHydrogen() outputs "H". Do not change or remove this line.
    releaseHydrogen();
    obj->HCount++;
    if(obj->HCount==2)
    {
        sem_post(&obj->O);//O元素信号量V操作
        obj->HCount = 0;
    }
}

void oxygen(H2O* obj) {
    sem_wait(&obj->O);
    // releaseOxygen() outputs "O". Do not change or remove this line.
    releaseOxygen();
    sem_post(&obj->H);
    sem_post(&obj->H);
}

void h2oFree(H2O* obj) {
    // User defined data may be cleaned up here.
    sem_destroy(&obj->O);
    sem_destroy(&obj->H);
}