ZBLOG

std::atomic m_lock;//队列正在析构

在 C++ 中,std::atomic<bool> 是一个用于实现原子操作的布尔类型,它保证了对该变量的读写操作是线程安全的。在您提到的上下文中,“队列正在析构”的意思可能是指一个多线程环境中的队列类,在其析构期间需要确保不会有其他线程访问该队列。

下面是如何使用 std::atomic<bool> 来标识队列是否正在被析构的一种示例实现:

示例代码

  1. #include <iostream>
  2. #include <thread>
  3. #include <queue>
  4. #include <atomic>
  5. #include <chrono>
  6. class ThreadSafeQueue {
  7. public:
  8. ThreadSafeQueue() : m_lock(false) {}
  9. void enqueue(int value) {
  10. std::unique_lock<std::mutex> lock(m_mutex);
  11. // 只有在队列没有被析构时才能入队
  12. if (!m_lock.load()) {
  13. m_queue.push(value);
  14. std::cout << "Enqueued: " << value << "\n";
  15. } else {
  16. std::cerr << "Cannot enqueue, queue is being destructed.\n";
  17. }
  18. }
  19. bool dequeue(int& result) {
  20. std::unique_lock<std::mutex> lock(m_mutex);
  21. if (!m_queue.empty() && !m_lock.load()) {
  22. result = m_queue.front();
  23. m_queue.pop();
  24. return true;
  25. }
  26. return false;
  27. }
  28. ~ThreadSafeQueue() {
  29. // 标记为正在析构
  30. m_lock.store(true);
  31. // 等待所有入队和出队操作完成(这里简单地休眠一下以演示)
  32. std::this_thread::sleep_for(std::chrono::milliseconds(100));
  33. while (!m_queue.empty()) {
  34. int value;
  35. dequeue(value); // 清空剩余元素
  36. std::cout << "Dequeued during destruction: " << value << "\n";
  37. }
  38. std::cout << "Queue destructed.\n";
  39. }
  40. private:
  41. std::queue<int> m_queue;
  42. mutable std::mutex m_mutex; // 互斥锁,用于保护访问共享资源
  43. std::atomic<bool> m_lock; // 用于标记是否正在析构
  44. };
  45. void producer(ThreadSafeQueue& q) {
  46. for (int i = 0; i < 5; ++i) {
  47. q.enqueue(i);
  48. std::this_thread::sleep_for(std::chrono::milliseconds(50));
  49. }
  50. }
  51. void consumer(ThreadSafeQueue& q) {
  52. int value;
  53. for (int i = 0; i < 5; ++i) {
  54. if (q.dequeue(value)) {
  55. std::cout << "Consumer got: " << value << "\n";
  56. } else {
  57. std::cerr << "Consumer couldn't dequeue.\n";
  58. }
  59. std::this_thread::sleep_for(std::chrono::milliseconds(60));
  60. }
  61. }
  62. int main() {
  63. ThreadSafeQueue queue;
  64. std::thread t1(producer, std::ref(queue));
  65. std::thread t2(consumer, std::ref(queue));
  66. t1.join();
  67. // 确保生产者先结束,再让消费者结束。
  68. std :: this_thread :: sleep_for(std :: chrono :: milliseconds (500));
  69. queue.~ThreadSafeQueue();
  70. t2.join();
  71. return 0;
  72. }

说明

  1. stdatomic:使用 stdatomic 可以确保对 m_lock 的读取和写入是原子的,避免了数据竞争的问题。

  2. 入队和出队方法:在 enqueue()dequeue() 方法中,我们首先检查 m_lock 是否为 false,以确保在队列未被销毁时才允许进行这些操作。

  3. 析构函数:在析构函数中,我们将 m_lock 设置为 true,表明当前对象正处于析构过程中。此后我们可以清空任何残留的数据,而不会影响到新的入队或出队操作。

  4. 多线程场景:为了演示这段代码,我们创建了一个生产者和消费者线程。这些线程会并发地对我们的线程安全队列进行操作。

这种设计模式确保了即使在多线程环境中,也能够正确地管理对资源的访问,并避免因同时访问而导致的不确定性行为。


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=22664

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?