交替打印FooBar

1 题目

我们提供一个类:

class FooBar {
  public void foo() {
    for (int i = 0; i < n; i++) {
      print("foo");
    }
  }

  public void bar() {
    for (int i = 0; i < n; i++) {
      print("bar");
    }
  }
}

两个不同的线程将会共用一个 FooBar 实例。其中一个线程将会调用 foo() 方法,另一个线程将会调用 bar() 方法。

请设计修改程序,以确保 "foobar" 被输出 n 次。

2 互锁

2.1 信号量

#include <semaphore.h>
class FooBar {
private:
    int n;

protected:
    sem_t foo_Done;
    sem_t bar_Done;

public:
    FooBar(int n) {
        this->n = n;
        sem_init(&foo_Done, 0, 1);
        sem_init(&bar_Done, 0, 0);
    }

    void foo(function<void()> printFoo) {
        for (int i = 0; i < n; i++) {
            sem_wait(&foo_Done);
            // printFoo() outputs "foo". Do not change or remove this line.
            printFoo();
            sem_post(&bar_Done);
        }
    }

    void bar(function<void()> printBar) {
        
        for (int i = 0; i < n; i++) {
            sem_wait(&bar_Done);
            // printBar() outputs "bar". Do not change or remove this line.
            printBar();
            sem_post(&foo_Done);
        }   
    }
};

运行时间: 320 ms

内存消耗: 8.1 MB

2.2 两个互斥锁

两个互斥锁容易出现死锁。

class FooBar {
private:
    int n;
    mutex mtx1, mtx2;

public:
    FooBar(int n) {
        this->n = n;
        mtx1.unlock();
        mtx2.lock();
    }

    void foo(function<void()> printFoo) {
        
        for (int i = 0; i < n; i++) {
            mtx1.lock();
            // printFoo() outputs "foo". Do not change or remove this line.
            printFoo();
            mtx2.unlock();
        }
    }

    void bar(function<void()> printBar) {
        
        for (int i = 0; i < n; i++) {
            mtx2.lock();
            // printBar() outputs "bar". Do not change or remove this line.
            printBar();
            mtx1.unlock();
        }
    }
};

运行时间: 380 ms

内存消耗: 8.3 MB

2.3 互斥锁+条件变量

class FooBar {
private:
    int n;
    mutex mtx;
    condition_variable cv;
    bool foo_done = false;
public:
    FooBar(int n) {
        this->n = n;
    }

    void foo(function<void()> printFoo) {
        for (int i = 0; i < n; i++) {
            unique_lock<mutex> lock(mtx);
            cv.wait(lock, [&]() { return !foo_done; });
            // printBar() outputs "foo". Do not change or remove this line.
            printFoo();
            foo_done = true;
            cv.notify_one();
        }
    }

    void bar(function<void()> printBar) {
        for (int i = 0; i < n; i++) {
            unique_lock<mutex> lock(mtx);
            cv.wait(lock, [&]() { return foo_done; });
	    // printBar() outputs "bar". Do not change or remove this line.
            printBar();
            foo_done = false;
            cv.notify_one();
        }
    }
};

运行时间: 320 ms

内存消耗: 8.2 MB

2.4 原子操作

c++11 特性

class FooBar {
private:
    int n;
    atomic<bool> foo_done = false;
public:
    FooBar(int n) {
        this->n = n;
    }

    void foo(function<void()> printFoo) {
        for (int i = 0; i < n; i++) {
            while (foo_done) {
                this_thread::yield();
            }
            printFoo();
            foo_done = true;
        }
    }

    void bar(function<void()> printBar) {
        for (int i = 0; i < n; i++) {
            while (!foo_done) {
                this_thread::yield();
            }
            printBar();
            foo_done = false;
        }
    }
};

2.5 无锁操作

class FooBar {
private:
    int n;
    bool foo_done = false;

public:
    FooBar(int n) {
        this->n = n;
    }

    void foo(function<void()> printFoo) {
        
        for (int i = 0; i < n; i++) {
            while(foo_done){
                std::this_thread::yield();
            }

            // printFoo() outputs "foo". Do not change or remove this line.
            printFoo();
            foo_done = true;
        }
    }

    void bar(function<void()> printBar) {
        
        for (int i = 0; i < n; i++) {
            while(!foo_done){
                std::this_thread::yield();
            }

            // printBar() outputs "bar". Do not change or remove this line.
            printBar();
            foo_done = false;
        }
    }
};

运行时间: 280 ms

内存消耗: 8.2 MB

posted @ 2021-02-14 22:06  iamwasabi  阅读(94)  评论(0)    收藏  举报