[LeetCode 1115.] 交替打印FooBar

LeetCode 1115. 交替打印FooBar

学到了一个新东西叫 this_thread

题目描述

我们提供一个类:

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 次。

示例 1:

输入: n = 1
输出: "foobar"
解释: 这里有两个线程被异步启动。其中一个调用 foo() 方法, 另一个调用 bar() 方法,"foobar" 将被输出一次。

示例 2:

输入: n = 2
输出: "foobarfoobar"
解释: "foobar" 将被输出两次。

解题思路

原子变量 + 自旋锁。
注意,这里用 while (next != 0); 来等待会超时,原因在于 while 循环并不会让出CPU。虽然题目说的是在两个线程内执行,但是测试环境并不一定真的是这么给的……
使用 C++11 提供的 this_thread::yield() 主动让出 CPU 更稳健一些。

参考代码

class FooBar {
private:
    int n;
    atomic<int> next = 0;

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

    void foo(function<void()> printFoo) {
        
        for (int i = 0; i < n; i++) {
            while (next != 0) this_thread::yield();
        	// printFoo() outputs "foo". Do not change or remove this line.
        	printFoo();
            next = 1;
        }
    }

    void bar(function<void()> printBar) {
        
        for (int i = 0; i < n; i++) {
            while (next != 1) this_thread::yield();
        	// printBar() outputs "bar". Do not change or remove this line.
        	printBar();
            next = 0;
        }
    }
};
posted @ 2021-07-26 15:14  与MPI做斗争  阅读(130)  评论(0编辑  收藏  举报