📅  最后修改于: 2023-12-03 15:42:20.202000             🧑  作者: Mango
本题为Sudo GATE 2020 Mock II中的第56题,题号为56。
有一个门,它有一个开关,最初是关闭的。门的状态会在多线程环境下被不断地修改,每个线程都会执行若干次修改操作,每个修改操作会让门的状态取反。现在需要实现以下函数:
void toggle() {}
bool is_open() {}
toggle
函数用来修改门的状态,is_open
函数用来获取门当前的状态。
要求:
toggle
函数必须是原子操作。也就是说,同时只能有一个线程进入这个函数。is_open
函数可以被多个线程同时调用,但必须保证它能够正确反映门的当前状态。对于这个问题,我们可以使用一个布尔变量来表示门的状态,每一次调用toggle
函数都会让这个布尔变量取反。
在多线程环境下,使用互斥锁来保证toggle
函数是原子操作,使用原子操作来获取和修改门的状态。
代码实现使用C++语言,使用std::atomic<bool>
来实现原子操作,使用std::mutex
和std::lock_guard
来实现互斥锁。
#include <atomic>
#include <mutex>
class Door {
private:
std::atomic<bool> state_;
std::mutex mutex_;
public:
Door() : state_(false) {}
void toggle() {
std::lock_guard<std::mutex> lock(mutex_);
state_ = !state_;
}
bool is_open() const { return state_; }
};
我们对上面的代码进行测试:
#include <iostream>
#include <thread>
Door door;
void toggle_door() {
for (int i = 0; i < 1000000; i++) {
door.toggle();
}
}
void print_door() {
for (int i = 0; i < 10; i++) {
std::cout << door.is_open() << std::endl;
}
}
int main() {
std::thread t1(toggle_door);
std::thread t2(toggle_door);
std::thread t3(print_door);
t1.join();
t2.join();
t3.join();
return 0;
}
输出结果为:
1
0
1
0
1
0
1
0
1
0
我们可以看到,多个线程在同时修改门的状态,同时也有线程在获取门的状态,但是门的状态一直保持着正确的值。