首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用shared_ptr进行多线程

用shared_ptr进行多线程
EN

Stack Overflow用户
提问于 2017-01-05 20:31:53
回答 4查看 2.7K关注 0票数 0

我需要在我的简单多线程应用程序,我正在使用作为一个简单的测试平台。我想要实现的是修改传递给多个线程的一个变量的值,最后读取结果。

代码语言:javascript
运行
复制
#include <iostream>
#include <memory>
#include <thread>
#include <mutex>

void updateValue(const std::shared_ptr<int>& value);

int main()
{
    auto sp = std::make_shared<int>(0);
    std::thread incrementThread_1(updateValue,sp);
    std::thread incrementThread_2(updateValue,sp);
    incrementThread_1.join();
    incrementThread_2.join();
    std::cout << *sp << std::endl;
}

void updateValue(const std::shared_ptr<int>& value)
{
    std::mutex g_i_mutex;
    for(int i = 0; i<100;i++)
    {
        std::unique_lock<std::mutex> lk(g_i_mutex);
        (*value)++;
        lk.unlock();
    }
}

目前它只是崩溃了。我在调试窗口中没有任何有意义的信息,所以它也没有帮助。有人能告诉我我可能做错了什么吗?

要指出的一点是-我不想使用全局变量,因为函数最初位于不同的文件中。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2017-01-05 21:28:20

线程之间共享的数据需要传送自己的互斥(与完全相同的线程集共享),并要求所有访问者同意使用互斥锁来序列化访问。

一个典型的解决方案是提供一个自定义类型来封装此责任。使用这种方法,代码大致如下所示:

代码语言:javascript
运行
复制
struct SyncInt
{
    int n = 0;
    std::mutex mx;
};

void updateValue(SyncInt & value)
{
    for (int i = 0; i != 100; ++i)
    {
        std::lock_guard<std::mutex> lock(value.mx);
        ++value.n;
    }
}

int main()
{
    SyncInt v;
    std::thread t1(updateValue, std::ref(v)), t2(updateValue, std::ref(v));
    t1.join();
    t2.join();
    std::cout << v.n << "\n";
}

(请注意,示例中的共享指针对于并发性问题并不重要,因为所有代码都只使用切入点,而不是指针本身。)

票数 2
EN

Stack Overflow用户

发布于 2017-01-05 21:13:22

目前它只是崩溃了。有人能告诉我我可能做错了什么吗?

您正在从两个不同的线程更新共享变量value,实际上没有任何同步。这是数据竞争条件,它是未定义的行为。修复它的最简单方法是使g_i_mutex成为全局的:

代码语言:javascript
运行
复制
#include <iostream>
#include <memory>
#include <thread>
#include <mutex>

std::mutex g_i_mutex;

void updateValue(const std::shared_ptr<int>& value);

int main()
{
    auto sp = std::make_shared<int>(0);
    std::thread incrementThread_1(updateValue,sp);
    std::thread incrementThread_2(updateValue,sp);
    incrementThread_1.join();
    incrementThread_2.join();
    std::cout << *sp << std::endl;
}

void updateValue(const std::shared_ptr<int>& value)
{
    for(int i = 0; i<100;i++)
    {
        std::unique_lock<std::mutex> lk(g_i_mutex);
        (*value)++;
        lk.unlock();
    }
}

另一个没有全局变量的解决方案:

代码语言:javascript
运行
复制
#include <iostream>
#include <memory>
#include <thread>
#include <mutex>

void updateValue(const std::shared_ptr<int>& value, std::mutex& g_i_mutex)
{
    for(int i = 0; i<100;i++)
    {
        std::unique_lock<std::mutex> lk(g_i_mutex);
        (*value)++;
        lk.unlock();
    }
}

int main()
{
    auto sp = std::make_shared<int>(0);
    std::mutex g_i_mutex;
    std::thread incrementThread_1(updateValue, sp, std::ref(g_i_mutex));
    std::thread incrementThread_2(updateValue, sp, std::ref(g_i_mutex));
    incrementThread_1.join();
    incrementThread_2.join();
    std::cout << *sp << std::endl;
}
票数 1
EN

Stack Overflow用户

发布于 2017-01-05 20:44:08

根据这个问题的优点,根本没有必要在这个场景中使用shared_ptr。你只需要一个atomic<int>

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41494158

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档