📌  相关文章
📜  门| Sudo GATE 2020 Mock II(2019 年 1 月 10 日)|第 56 题(1)

📅  最后修改于: 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::mutexstd::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

我们可以看到,多个线程在同时修改门的状态,同时也有线程在获取门的状态,但是门的状态一直保持着正确的值。