• leetcode 线程题 1114. 按序打印


    给你一个类:

    public class Foo {
      public void first() { print("first"); }
      public void second() { print("second"); }
      public void third() { print("third"); }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    三个不同的线程 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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    方法二:信号量
    #include

    信号量的数据类型为结构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));
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    方法三:线程

    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);
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
  • 相关阅读:
    Kubernetes kafka系列 | k8s部署kafka+zookeepe集群
    scrapy爬取图片
    TypeScript系列之类型 string
    微服务开发步骤(nacos)
    C++新经典 | C++ 查漏补缺(内存)
    numpy的基本操作
    云计算发展的十年IaaS、Paas、SaaS、APaaS
    CSS语法及其选择器
    【自用】三阶段项目-起步
    XTU-OJ 1169-最大子段和
  • 原文地址:https://blog.csdn.net/weixin_43786143/article/details/126483385