鱼C论坛

 找回密码
 立即注册
查看: 198|回复: 1

[已解决]C++ 多线程报错访问冲突

[复制链接]
发表于 2024-2-25 12:44:11 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
我在尝试做一个生产者+消费者多线程模型的时候,在进行调试时,出现报错:
0xC0000005: 读取位置 0x0000000000000070 时发生访问冲突。
以下是我的源代码(生产者部分被略去):
  1. export module core.thread;
  2. import std;
  3. import core.constants;

  4. using function = std::function<void()>;
  5. using lock = std::lock_guard<std::mutex>;

  6. export namespace thread
  7. {
  8.         class Group
  9.         {
  10.                 protected:
  11.                 std::queue<function> queue;
  12.                 public:
  13.                 std::condition_variable variable;
  14.                 std::mutex mutex;
  15.                 Group() = default;
  16.                 Group(const Group&) = delete;
  17.                 Group(Group&&) = delete;
  18.                 std::optional<function> get_task() noexcept
  19.                 {
  20.                         lock lock(this->mutex);
  21.                         if (this->queue.empty())
  22.                         {
  23.                                 return std::nullopt;
  24.                         };
  25.                         function task = this->queue.front();
  26.                         this->queue.pop();
  27.                         return task;
  28.                 };
  29.                 void add_task(function task) noexcept
  30.                 {
  31.                         lock lock(this->mutex);
  32.                         this->queue.push(task);
  33.                         this->variable.notify_one();
  34.                 };
  35.         };

  36.         class BasicThread
  37.         {
  38.                 protected:
  39.                         std::thread thread;
  40.                         choice::status status;
  41.                         std::string name;
  42.                 public:
  43.                         BasicThread() = delete;
  44.                         BasicThread(const BasicThread&) = delete;
  45.                         BasicThread(BasicThread&&) = default;
  46.                         BasicThread(const std::string& name) :
  47.                                 name(name)
  48.                         {
  49.                                 this->thread = std::thread(&BasicThread::run, this);
  50.                         };
  51.                         virtual void run() {};
  52.                         inline void join() noexcept
  53.                         {
  54.                                 if (this->thread.joinable())
  55.                                 {
  56.                                         this->thread.join();
  57.                                 };
  58.                         };
  59.         };

  60.         class Worker : public BasicThread
  61.         {
  62.                 protected:
  63.                         std::shared_ptr<Group> group;
  64.                 public:
  65.                         Worker() = delete;
  66.                         Worker(const Worker&) = delete;
  67.                         Worker(Worker&&) = default;
  68.                         Worker(const std::string& name, const std::shared_ptr<Group>& group) :
  69.                                 BasicThread(name),
  70.                                 group(group) {};
  71.                         void run()
  72.                         {
  73.                                 std::optional<function> current_task;
  74.                                 while (this->status != choice::status::terminating)
  75.                                 {
  76.                                         std::unique_lock<std::mutex> lock{ this->group->mutex };
  77.                                         this->group->variable.wait(lock, [&current_task, this]() {return current_task = this->group->get_task(); }); // Only runs if a new task is available
  78.                                         lock.unlock();
  79.                                         current_task.value()();
  80.                                 };
  81.                         };
  82.                         inline void attach(const std::shared_ptr<Group>& group) noexcept
  83.                         {
  84.                                 this->group = group;
  85.                         };
  86.         };
  87. };
复制代码

这是我的调试部分:
  1. import core.thread;
  2. import std;

  3. int main()
  4. {
  5.         std::shared_ptr<thread::Group> group;
  6.         thread::Worker worker{ "test", group };
  7.         return 0;
  8. };
复制代码
最佳答案
2024-2-25 12:44:30
你好!你的代码中存在一些问题导致了访问冲突的报错。首先,你在主函数中定义了一个名为`group`的`std::shared_ptr`智能指针,但没有初始化它,所以会导致未定义的行为。你需要为`group`分配内存并初始化它,可以使用`std::make_shared`函数来实现:

  1. std::shared_ptr<thread::Group> group = std::make_shared<thread::Group>();
复制代码


其次,在`Worker`类的构造函数中,你将`std::shared_ptr`对象传递给了`group`成员,但是在声明`group`时,没有指定它指向的具体类型,这也是引起编译错误的原因。你需要明确指出`group`指向的是`thread::Group`类型:

  1. std::shared_ptr<thread::Group> group;
复制代码


但是请注意,这只是修复了编译错误,而不是解决访问冲突的问题。要解决访问冲突,你还需要对多线程间的共享资源进行正确的加锁处理。在你的代码中,生产者通过添加任务到队列中来共享资源,消费者通过从队列中获取任务来共享资源。

你可以在生产者添加任务时加锁,以及在消费者获取任务时加锁:

  1. // 生产者
  2. void add_task(function task) noexcept
  3. {
  4.     lock lock(this->mutex);
  5.     this->queue.push(task);
  6.     this->variable.notify_one();
  7. };

  8. // 消费者
  9. void run()
  10. {
  11.     std::optional<function> current_task;
  12.     while (this->status != choice::status::terminating)
  13.     {
  14.         std::unique_lock<std::mutex> lock(this->group->mutex);
  15.         this->group->variable.wait(lock, [this]() { return !this->group->queue.empty(); }); // 只有当队列非空时才继续执行
  16.         current_task = this->group->get_task();
  17.         lock.unlock();
  18.         if (current_task.has_value())
  19.         {
  20.             current_task.value()();
  21.         }
  22.     }
  23. }
复制代码


这样做的目的是保证在生产者和消费者之间正确地同步资源访问。通过加锁,确保只有一个线程能够同时对资源进行访问,避免访问冲突的问题。

希望以上解答能够帮助到你!如果还有其他问题,请随时提问。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-2-25 12:44:30 | 显示全部楼层    本楼为最佳答案   
你好!你的代码中存在一些问题导致了访问冲突的报错。首先,你在主函数中定义了一个名为`group`的`std::shared_ptr`智能指针,但没有初始化它,所以会导致未定义的行为。你需要为`group`分配内存并初始化它,可以使用`std::make_shared`函数来实现:

  1. std::shared_ptr<thread::Group> group = std::make_shared<thread::Group>();
复制代码


其次,在`Worker`类的构造函数中,你将`std::shared_ptr`对象传递给了`group`成员,但是在声明`group`时,没有指定它指向的具体类型,这也是引起编译错误的原因。你需要明确指出`group`指向的是`thread::Group`类型:

  1. std::shared_ptr<thread::Group> group;
复制代码


但是请注意,这只是修复了编译错误,而不是解决访问冲突的问题。要解决访问冲突,你还需要对多线程间的共享资源进行正确的加锁处理。在你的代码中,生产者通过添加任务到队列中来共享资源,消费者通过从队列中获取任务来共享资源。

你可以在生产者添加任务时加锁,以及在消费者获取任务时加锁:

  1. // 生产者
  2. void add_task(function task) noexcept
  3. {
  4.     lock lock(this->mutex);
  5.     this->queue.push(task);
  6.     this->variable.notify_one();
  7. };

  8. // 消费者
  9. void run()
  10. {
  11.     std::optional<function> current_task;
  12.     while (this->status != choice::status::terminating)
  13.     {
  14.         std::unique_lock<std::mutex> lock(this->group->mutex);
  15.         this->group->variable.wait(lock, [this]() { return !this->group->queue.empty(); }); // 只有当队列非空时才继续执行
  16.         current_task = this->group->get_task();
  17.         lock.unlock();
  18.         if (current_task.has_value())
  19.         {
  20.             current_task.value()();
  21.         }
  22.     }
  23. }
复制代码


这样做的目的是保证在生产者和消费者之间正确地同步资源访问。通过加锁,确保只有一个线程能够同时对资源进行访问,避免访问冲突的问题。

希望以上解答能够帮助到你!如果还有其他问题,请随时提问。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-28 22:06

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表