码迷,mamicode.com
首页 > 编程语言 > 详细

LeetCode——H2O生成(多线程)

时间:2020-03-17 17:57:35      阅读:83      评论:0      收藏:0      [点我收藏+]

标签:typedef   文件   数值   create   red   函数   read   大于   etc   

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。

方案一:

两个锁,h线程拿t2锁,打印两次后,释放t1锁,给O线程
O线程拿t1锁,打印后,释放t2锁,再等下一个h线程的t1锁释放

typedef struct {
    // User defined data may be declared here.
    pthread_mutex_t t1;
    pthread_mutex_t t2;
    int i;
} H2O;

H2O* h2oCreate() {
    H2O* obj = (H2O*) malloc(sizeof(H2O));
    
    // Initialize user defined data here.
    pthread_mutex_init(&obj->t1, NULL);
    pthread_mutex_init(&obj->t2, NULL);
    obj->i = 0;
    return obj;
}

void hydrogen(H2O* obj) {
    // releaseHydrogen() outputs "H". Do not change or remove this line.
    pthread_mutex_lock(&obj->t2);
    releaseHydrogen();
    obj->i++;
    if (obj->i == 2) {
        pthread_mutex_unlock(&obj->t1);
        obj->i = 0;
    }
    else
        pthread_mutex_unlock(&obj->t2);
}

void oxygen(H2O* obj) {
    
    // releaseOxygen() outputs "O". Do not change or remove this line.
    pthread_mutex_lock(&obj->t1);
    releaseOxygen();
    
    pthread_mutex_unlock(&obj->t2);
}

void h2oFree(H2O* obj) {
    // User defined data may be cleaned up here.
    free(obj);
}

方案二:C++信号量版本

信号量相关函数及定义

linux 信号量相关函数都声明头文件 semaphore.h 头文件中,所以使用信号量之前需要先包含头文件

#include <semaphore.h>

信号量的创建就像声明一般的变量一样简单,例如:sem_t sem,之后对该信号量进行初始化和使用。

  • sem_init

该函数用于创建信号量,其原型如下:

int sem_init(sem_t *sem, int pshared, unsigned int value);

该函数初始化由 sem 指向的信号对象,并给它一个初始的整数值 value。

pshared 控制信号量的类型,值为 0 代表该信号量用于多线程间的同步,值如果大于 0 表示可以共享,用于多个相关进程间的同步

参数 pshared > 0 时指定了 sem 处于共享内存区域,所以可以在进程间共享该变量
  • sem_wait
int sem_wait(sem_t *sem); 
int sem_trywait(sem_t *sem);

sem_wait 是一个阻塞的函数,测试所指定信号量的值,它的操作是原子的。若 sem value > 0,则该信号量值减去 1 并立即返回。若sem value = 0,则阻塞直到 sem value > 0,此时立即减去 1,然后返回。

sem_trywait 函数是非阻塞的函数,它会尝试获取获取 sem value 值,如果 sem value = 0,不是阻塞住,而是直接返回一个错误 EAGAIN。

  • sem_post
    把指定的信号量 sem 的值加 1,唤醒正在等待该信号量的任意线程。
int sem_post(sem_t *sem);
  • sem_getvalue
int sem_getvalue(sem_t *sem, int *sval);

获取信号量 sem 的当前值,把该值保存在 sval,若有 1 个或者多个线程正在调用 sem_wait 阻塞在该信号量上,该函数返回阻塞在该信号量上进程或线程个数。

  • sem_destroy

该函数用于对用完的信号量的清理。它的原型如下:

int sem_destroy(sem_t *sem);
#include <semaphore.h>
class H2O {
public:
H2O() {
    sem_init(&h_limit, 0, 2);
    sem_init(&o_limit, 0, 0);
}
~H2O() {
    sem_destroy(&h_limit);
    sem_destroy(&o_limit);
}

void hydrogen(function<void()> releaseHydrogen) {
    
    // releaseHydrogen() outputs "H". Do not change or remove this line.
    sem_wait(&h_limit);
    releaseHydrogen();
    count_h++;
    if(count_h == 2){
      count_h = 0;
      sem_post(&o_limit);
    }   
}

void oxygen(function<void()> releaseOxygen) {
    
    // releaseOxygen() outputs "O". Do not change or remove this line.
    sem_wait(&o_limit);
    releaseOxygen();
    sem_post(&h_limit);
    sem_post(&h_limit);
}

private:
    int count_h = 0;
    sem_t h_limit;
    sem_t o_limit;
};

LeetCode——H2O生成(多线程)

标签:typedef   文件   数值   create   red   函数   read   大于   etc   

原文地址:https://www.cnblogs.com/beimangshanxiaoqigui/p/12512293.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!