Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用共享ptr的多线程处理_C++_Multithreading_C++11 - Fatal编程技术网

C++ 使用共享ptr的多线程处理

C++ 使用共享ptr的多线程处理,c++,multithreading,c++11,C++,Multithreading,C++11,我把我的简单多线程应用程序作为一个简单的测试平台。我想要实现的是修改传递给多个线程的一个变量的值,并在所有操作完成后读取结果 #include <iostream> #include <memory> #include <thread> #include <mutex> void updateValue(const std::shared_ptr<int>& value); int main() { auto sp

我把我的简单多线程应用程序作为一个简单的测试平台。我想要实现的是修改传递给多个线程的一个变量的值,并在所有操作完成后读取结果

#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();
    }
}
#包括
#包括
#包括
#包括
void updateValue(const std::shared_ptr&value);
int main()
{
自动sp=std::使_共享(0);
线程递增线程1(更新值,sp);
std::thread incrementThread_2(updateValue,sp);
递增线程_1.join();
递增线程_2.join();

std::cout关于这个问题的优点,在这个场景中根本不需要使用
共享\u ptr
。您所需要的只是一个
原子的

您想要使用这样的数据结构,它将您的互斥锁与其保护访问的数据块紧密地联系在一起:

class somethingShared
{
    int        m_value;
    std::mutex m_mtx;

    public:
    somethingShared( int initialVal ) : m_value( initialVal ) { }

    void increment()
    {
        std::unique_lock<std::mutex> lk(m_mtx);
        ++m_value;
    }

    int value() const { return m_value; }

};

void updateValue( somethingShared & value)
{
    for ( int i = 0; i < 100; ++i )
    {
        value.increment();
    }
}
class somethingShared
{
int m_值;
std::mutex m_mtx;
公众:
somethingShared(int initialVal):m_值(initialVal){}
无效增量()
{
std::唯一锁定lk(m_mtx);
++m_值;
}
int value()常量{返回m_值;}
};
void updateValue(something共享和值)
{
对于(int i=0;i<100;++i)
{
value.increment();
}
}
注意,我还没有编译或运行这个,它只是为了展示一般的想法

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

您正在从两个不同的线程更新共享变量
,实际上没有任何同步。这是数据争用条件,是未定义的行为。解决它的最简单方法是使
g_i_互斥体
全局:

#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();
    }
}
#包括
#包括
#包括
#包括
std::mutex g_i_mutex;
void updateValue(const std::shared_ptr&value);
int main()
{
自动sp=std::使_共享(0);
线程递增线程1(更新值,sp);
std::thread incrementThread_2(updateValue,sp);
递增线程_1.join();
递增线程_2.join();

线程之间共享的数据需要提供自己的互斥体(与完全相同的线程集共享),并要求所有访问器同意使用该互斥体来序列化访问

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

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";
}
struct-SyncInt
{
int n=0;
std::互斥体mx;
};
void updateValue(SyncInt和value)
{
对于(int i=0;i!=100;++i)
{
std::锁和保护锁(value.mx);
++数值n;
}
}
int main()
{
SyncInt v;
线程t1(updateValue,std::ref(v)),t2(updateValue,std::ref(v));
t1.join();
t2.连接();

std::cout每个线程都有自己的互斥锁有什么意义?为什么要手动解锁
unique\u lock
?你做错了一件事,就是
gi\u互斥锁
是一个局部变量,所以每个线程都会有自己的副本,所以你永远不会不获取互斥锁。换句话说,如果你的意图是让每个线程获取对共享的
int
的独占访问权,这将不起作用。为此,每个线程必须锁定相同的互斥体。显示的代码为每个线程使用单独的互斥体。这绝对没有任何用处。每个线程都有自己的
std::mutex
,这并不是您所期望的。您需要传递一个单独的实例,就像你在传递一个
int
@sebap123一样,你不需要一个
共享的互斥体。但是你需要做的是与两个线程共享一个互斥体。你可以通过引用每个线程来传递它,或者使它成为全局的。在任何在线编译器中尝试它,你都会看到。一点都不是v非常有用。我认为还应该是
value()
访问器中的一个锁,尽管在本例中,它可能在没有它的情况下工作(由于thread.join同步)。将线程创建替换为
std::thread incrementThread_1([&sp](){updateValue(sp);});
,否则它将尝试复制共享的内容,这是不可能的。好吧,如果我有全局互斥,那就行了。我知道这是一个解决方案,但我不能这样做(我甚至在问题中强调了它)。非常感谢你。我从未想过将结构用作容器。
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";
}