鱼C论坛

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

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

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

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

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

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

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

export namespace thread
{
        class Group
        {
                protected:
                std::queue<function> queue;
                public:
                std::condition_variable variable;
                std::mutex mutex;
                Group() = default;
                Group(const Group&) = delete;
                Group(Group&&) = delete;
                std::optional<function> get_task() noexcept
                {
                        lock lock(this->mutex);
                        if (this->queue.empty())
                        {
                                return std::nullopt;
                        };
                        function task = this->queue.front();
                        this->queue.pop();
                        return task;
                };
                void add_task(function task) noexcept
                {
                        lock lock(this->mutex);
                        this->queue.push(task);
                        this->variable.notify_one();
                };
        };

        class BasicThread
        {
                protected:
                        std::thread thread;
                        choice::status status;
                        std::string name;
                public:
                        BasicThread() = delete;
                        BasicThread(const BasicThread&) = delete;
                        BasicThread(BasicThread&&) = default;
                        BasicThread(const std::string& name) :
                                name(name)
                        {
                                this->thread = std::thread(&BasicThread::run, this);
                        };
                        virtual void run() {};
                        inline void join() noexcept
                        {
                                if (this->thread.joinable())
                                {
                                        this->thread.join();
                                };
                        };
        };

        class Worker : public BasicThread
        {
                protected:
                        std::shared_ptr<Group> group;
                public:
                        Worker() = delete;
                        Worker(const Worker&) = delete;
                        Worker(Worker&&) = default;
                        Worker(const std::string& name, const std::shared_ptr<Group>& group) :
                                BasicThread(name),
                                group(group) {};
                        void run()
                        {
                                std::optional<function> current_task;
                                while (this->status != choice::status::terminating)
                                {
                                        std::unique_lock<std::mutex> lock{ this->group->mutex };
                                        this->group->variable.wait(lock, [¤t_task, this]() {return current_task = this->group->get_task(); }); // Only runs if a new task is available
                                        lock.unlock();
                                        current_task.value()();
                                };
                        };
                        inline void attach(const std::shared_ptr<Group>& group) noexcept
                        {
                                this->group = group;
                        };
        };
};
这是我的调试部分:
import core.thread;
import std;

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

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

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

你可以在生产者添加任务时加锁,以及在消费者获取任务时加锁:
// 生产者
void add_task(function task) noexcept
{
    lock lock(this->mutex);
    this->queue.push(task);
    this->variable.notify_one();
};

// 消费者
void run()
{
    std::optional<function> current_task;
    while (this->status != choice::status::terminating)
    {
        std::unique_lock<std::mutex> lock(this->group->mutex);
        this->group->variable.wait(lock, [this]() { return !this->group->queue.empty(); }); // 只有当队列非空时才继续执行
        current_task = this->group->get_task();
        lock.unlock();
        if (current_task.has_value())
        {
            current_task.value()();
        }
    }
}

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

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

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

使用道具 举报

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

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

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

你可以在生产者添加任务时加锁,以及在消费者获取任务时加锁:
// 生产者
void add_task(function task) noexcept
{
    lock lock(this->mutex);
    this->queue.push(task);
    this->variable.notify_one();
};

// 消费者
void run()
{
    std::optional<function> current_task;
    while (this->status != choice::status::terminating)
    {
        std::unique_lock<std::mutex> lock(this->group->mutex);
        this->group->variable.wait(lock, [this]() { return !this->group->queue.empty(); }); // 只有当队列非空时才继续执行
        current_task = this->group->get_task();
        lock.unlock();
        if (current_task.has_value())
        {
            current_task.value()();
        }
    }
}

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

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

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-12-22 17:57

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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