leetcode No1114. Print in Order

Question

Suppose we have a class:

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

The same instance of Foo will be passed to three different threads. Thread A will call first(), thread B will call second(), and thread C will call third(). Design a mechanism and modify the program to ensure that second() is executed after first(), and third() is executed after second().

Example 1:

Input: [1,2,3]
Output: "firstsecondthird"
Explanation: There are three threads being fired asynchronously. The input [1,2,3] means thread A calls first(), thread B calls second(), and thread C calls third(). "firstsecondthird" is the correct output.

Example 2:

Input: [1,3,2]
Output: "firstsecondthird"
Explanation: The input [1,3,2] means thread A calls first(), thread B calls third(), and thread C calls second(). "firstsecondthird" is the correct output.

Note:

We do not know how the threads will be scheduled in the operating system, even though the numbers in the input seems to imply the ordering. The input format you see is mainly to ensure our tests’ comprehensiveness.

Algorithm

leetcode越來越強大了,也有多線程的題目了,不得不說這些題目確實對理解多線程很有幫助。這一題是按順序打印字串,看到按順序這三個字。

C++多線程同步的幾種方式

Code

semaphore
C++11 和 Boost.Thread 都沒有提供信號量,簡單來說,就是信號量太容易出錯了(too error prone),通過組合互斥鎖(mutex)和條件變量(condition variable)可以達到相同的效果,且更加安全。更詳細的講解請看:C++ 併發編程(六):信號量(Semaphore)

  • 執行用時 :156 ms, 在所有 cpp 提交中擊敗了23.83%的用戶
  • 內存消耗 :9 MB, 在所有 cpp 提交中擊敗了100.00%的用戶
#include <semaphore.h>
class Foo {
public:
    sem_t sem_one;
    sem_t sem_two;

    Foo() {
        sem_init(&sem_one, 0, 0);    
        sem_init(&sem_two, 0, 0);    
    }

    void first(function<void()> printFirst) {
        // printFirst() outputs "first". Do not change or remove this line.
        printFirst();
        sem_post(&sem_one);
    }

    void second(function<void()> printSecond) {
        sem_wait(&sem_one);
        // printSecond() outputs "second". Do not change or remove this line.
        printSecond();
        sem_post(&sem_two);
    }

    void third(function<void()> printThird) {
        sem_wait(&sem_two);
        // printThird() outputs "third". Do not change or remove this line.
        printThird();
    }
};

mutex

  • 執行用時 :152 ms, 在所有 cpp 提交中擊敗了23.97%的用戶
  • 內存消耗 :9 MB, 在所有 cpp 提交中擊敗了100.00%的用戶
class Foo {
public:
    pthread_mutex_t mutex1;
    pthread_mutex_t mutex2;

    Foo() {
        pthread_mutex_init(&mutex1, NULL);
        pthread_mutex_init(&mutex2, NULL);

        pthread_mutex_lock(&mutex1);
        pthread_mutex_lock(&mutex2);
    }

    void first(function<void()> printFirst) {
        // printFirst() outputs "first". Do not change or remove this line.
        printFirst();
        pthread_mutex_unlock(&mutex1);
    }

    void second(function<void()> printSecond) {
        pthread_mutex_lock(&mutex1);
        // printSecond() outputs "second". Do not change or remove this line.
        printSecond();
        pthread_mutex_unlock(&mutex2);
    }

    void third(function<void()> printThird) {
        pthread_mutex_lock(&mutex2);
        // printThird() outputs "third". Do not change or remove this line.
        printThird();
    }
};

condition variable

class Foo {
public:
    mutex m;

    condition_variable cv1;
    condition_variable cv2;

    bool second_ready = false;
    bool third_ready = false;

    Foo() { 
    }

    void first(function<void()> printFirst) {
        unique_lock<mutex> lk(m);
        // printFirst() outputs "first". Do not change or remove this line.
        printFirst();
        second_ready = true;
        cv1.notify_one();
    }

    void second(function<void()> printSecond) {
        unique_lock<mutex> lk(m);
        cv1.wait(lk,[this](){return second_ready == true;});
        // printSecond() outputs "second". Do not change or remove this line.
        printSecond();
        third_ready = true;
        cv2.notify_one();
    }

    void third(function<void()> printThird) {
        unique_lock<mutex> lk(m);
        cv2.wait(lk,[this](){return third_ready == true;});
        // printThird() outputs "third". Do not change or remove this line.
        printThird();
    }
};

promise/future

class Foo {
public:
    promise<int> p1,p2;
    Foo() {
        
    }

    void first(function<void()> printFirst) {
        
        // printFirst() outputs "first". Do not change or remove this line.
        printFirst();
        p1.set_value(0);
    }

    void second(function<void()> printSecond) {
        p1.get_future().wait();
        // printSecond() outputs "second". Do not change or remove this line.
        printSecond();
        p2.set_value(0);
    }

    void third(function<void()> printThird) {
        p2.get_future().wait();
        // printThird() outputs "third". Do not change or remove this line.
        printThird();
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章