leetcode 线程题 1114. 按序打印

简介: leetcode 线程题 1114. 按序打印

给你一个类:

public class Foo {
  public void first() { print("first"); }
  public void second() { print("second"); }
  public void third() { print("third"); }
}

三个不同的线程 A、B、C 将会共用一个 Foo 实例。


线程 A 将会调用 first() 方法

线程 B 将会调用 second() 方法

线程 C 将会调用 third() 方法

请设计修改程序,以确保 second() 方法在 first() 方法之后被执行,third() 方法在 second() 方法之后被执行。

提示:

尽管输入中的数字似乎暗示了顺序,但是我们并不保证线程在操作系统中的调度顺序。

你看到的输入格式主要是为了确保测试的全面性。


方法一:信号量while?

typedef struct {
    // User defined data may be declared here.
    int mutex_1;
    // int mutex_2;
} Foo;
Foo* fooCreate() {
    Foo* obj = (Foo*) malloc(sizeof(Foo));
    // Initialize user defined data here.
    obj->mutex_1 = 1;
    // obj->mutex_2 = 1;//初始化
    return obj;
}
void first(Foo* obj) {
    // printFirst() outputs "first". Do not change or remove this line.
    while(obj->mutex_1!=1);
    printFirst();
    obj->mutex_1 = 2;
}
void second(Foo* obj) {
    // printSecond() outputs "second". Do not change or remove this line.
    while(obj->mutex_1!=2);
    printSecond();
    obj->mutex_1 = 3;
}
void third(Foo* obj) {
    while(obj->mutex_1!=3);
    // printThird() outputs "third". Do not change or remove this line.
    printThird();
}
void fooFree(Foo* obj) {
    // User defined data may be cleaned up here.
    free(obj);
}

方法二:信号量

#include<semaphore.h>


信号量的数据类型为结构sem_t,它本质上是一个长整型的数。


函数sem_init()用来初始化一个信号量。它的原型为:int sem_init __P ((sem_t *__sem, int __pshared, unsigned int __value));sem为指向信号量结构的一个指针;pshared不为0时此信号量在进程间共享,否则只能为当前进程的所有线程共享;value给出了信号量的初始值。信号量用sem_init函数创建的,下面是它的说明:

int sem_init (sem_t *sem, int pshared, unsigned int value); 这个函数的作用是对由sem指定的信号量进行初始化,设置好它的共享选项,并指定一个整数类型的初始值。pshared参数控制着信号量的类型。如果 pshared的值是0,就表示它是当前里程的局部信号量;否则,其它进程就能够共享这个信号量。我们现在只对不让进程共享的信号量感兴趣。 (这个参数 受版本影响), pshared传递一个非零将会使函数调用失败,属于无名信号量。  

函数sem_post( sem_t *sem )用来增加信号量的值。当有线程阻塞在这个信号量上时,调用这个函数会使其中的一个线程不在阻塞,选择机制同样是由线程的调度策略决定的。int sem_post(sem_t *sem);sem_post() 成功时返回 0;错误时,信号量的值没有更改,-1 被返回,并设置errno 来指明错误。错误 EINVAL  sem 不是一个有效的信号量。  EOVERFLOW 信号量允许的最大值将要被超过。


函数sem_wait( sem_t *sem )被用来阻塞当前线程直到信号量sem的值大于0,解除阻塞后将sem的值减一,表明公共资源经使用后减少。


函数sem_destroy(sem_t *sem)用来释放信号量sem,属于无名信号量。

typedef struct {
    // User defined data may be declared here.
    sem_t one;
    sem_t two;
} Foo;
Foo* fooCreate() {
    Foo* obj = (Foo*) malloc(sizeof(Foo));
    sem_init(&(obj->one), 0, 0);
    sem_init(&(obj->two), 0, 0);
    // Initialize user defined data here.
    return obj;
}
void first(Foo* obj) {
    // printFirst() outputs "first". Do not change or remove this line.
    printFirst();
    sem_post(&(obj->one));
}
void second(Foo* obj) {
    // printSecond() outputs "second". Do not change or remove this line.
    sem_wait(&(obj->one));
    printSecond();
    sem_post(&(obj->two));
}
void third(Foo* obj) {
    sem_wait(&(obj->two));
    // printThird() outputs "third". Do not change or remove this line.
    printThird();
}
void fooFree(Foo* obj) {
    // User defined data may be cleaned up here.
    sem_destroy(&(obj->one));
    sem_destroy(&(obj->two));
}

方法三:线程

typedef struct {
    pthread_mutex_t mutex_1;
    pthread_mutex_t mutex_2;  //创建互斥锁
} Foo;
Foo* fooCreate() {
    Foo* obj = (Foo*) malloc(sizeof(Foo));
    pthread_mutex_init(&obj->mutex_1, NULL);
    pthread_mutex_init(&obj->mutex_2, NULL);
    pthread_mutex_lock(&obj->mutex_1);
    pthread_mutex_lock(&obj->mutex_2);
    return obj;
}
void first(Foo* obj) {
    printFirst();
    pthread_mutex_unlock(&obj->mutex_1);
}
void second(Foo* obj) {
    pthread_mutex_lock(&obj->mutex_1);     //阻塞调用 获取锁
    printSecond();
    pthread_mutex_unlock(&obj->mutex_1);   
    pthread_mutex_unlock(&obj->mutex_2);
}
void third(Foo* obj) {
    pthread_mutex_lock(&obj->mutex_2);
    printThird();
    pthread_mutex_unlock(&obj->mutex_2);  //释放互斥锁
}
void fooFree(Foo* obj) {
    pthread_mutex_destroy(&obj->mutex_1);
    pthread_mutex_destroy(&obj->mutex_2); //销毁互斥锁
    free(obj);
}
相关文章
|
4月前
|
数据采集 负载均衡 安全
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
本文提供了多个多线程编程问题的解决方案,包括设计有限阻塞队列、多线程网页爬虫、红绿灯路口等,每个问题都给出了至少一种实现方法,涵盖了互斥锁、条件变量、信号量等线程同步机制的使用。
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
|
8月前
Leetcode之多线程编程题
现有函数 printNumber 可以用一个整数参数调用,并输出该整数到控制台。 例如,调用 printNumber(7) 将会输出 7 到控制台。 给你类 ZeroEvenOdd 的一个实例,该类中有三个函数:zero、even 和 odd 。ZeroEvenOdd 的相同实例将会传递给三个不同线程:
124 1
|
数据采集
LeetCode(多线程)- 1242. 多线程网页爬虫
LeetCode(多线程)- 1242. 多线程网页爬虫
233 0
|
调度
leetcode.1114-按序打印-多线程案例
leetcode.1114-按序打印-多线程案例
115 0
leetcode线程题1116——打印零与奇偶数
leetcode线程题1116——打印零与奇偶数
109 0
leetcode线程题1117——H2O 生成(两个氢原子结合一个氧原子)
leetcode线程题1117——H2O 生成(两个氢原子结合一个氧原子)
106 0
LeetCode(多线程)- 题集
LeetCode(多线程)- 题集
121 0
LeetCode(多线程)- 题集
|
C语言 C++
【LeetCode1114】按序打印(多线程,信号量)
第一次在leetcode上做这种多线程题目,对于这种“同步”问题,需要明白线程在哪里需要阻塞(对应PV操作中的P),再找对应的V部分(释放资源)。并且题目这里不要求考察临界资源的访问(互斥关系),只需要考虑同步关系。先想的printB之前需要阻塞,因为需要等A完成打印,所
167 0
【LeetCode1114】按序打印(多线程,信号量)
LeetCode(多线程)- 1279. 红绿灯路口
LeetCode(多线程)- 1279. 红绿灯路口
349 0
LeetCode(多线程)- 1226. 哲学家进餐
LeetCode(多线程)- 1226. 哲学家进餐
115 0