C ++中的多线程数据同步

时间:2016-05-26 16:26:15

标签: c++ multithreading

这是我的问题。我有几个线程修改了struture的attributs,我有一个读取结构的线程。我如何确定我正在读取的值不会被其他线程更改?在我的情况下,属性只能由一个线程修改。

例:

typedef struct
{
    int a;
    double b;

} data;

data glob;

int main()
{

    thread reader([]()
    {
        while(1)
        {
            sleep(1s);
            cout << glob;
        }
    });

    thread writer1([]()
    { 
        while(1)
            glob.a++;
    });
    thread writer2([]()
    { 
        while(1)
            glob.b++;
    });


    int i;
    cin >>i;
}

然后,我怎么能确定当我读取glob时,它不会被writer1和writer2修改?

2 个答案:

答案 0 :(得分:4)

#include <thread>
#include <atomic>
#include <iostream>
#include<chrono>

typedef struct
{
    std::atomic_int a;
    std::atomic<double> b;



} data;



data glob;


int main()
{
    glob.a.store(0);//store data in the atomic variable
    glob.b.store(0.0);

    std::thread reader([]()
    {
        while (1)
        {
            std::this_thread::sleep_for(std::chrono::seconds(1));
            std::cout << glob.a.load() << " " << glob.b.load() << std::endl; //get the value of the variable
        }
    });

    std::thread writer1([]()
    {
        while (1)
            glob.a++;
    });
    std::thread writer2([]()
    {
        while (1)
            glob.b.store(glob.b.load() +1); // std::atomic<double> has no member operator++ so have to improvise
    });


    int i;
    std::cin >> i;
}

对于使用<atomic>进行不可分割的访问和写入操作的问题,这是一个简单的解决方案。

答案 1 :(得分:0)

使用互斥锁,一旦你了解它就非常简单。

http://en.cppreference.com/w/cpp/thread/mutex

http://en.cppreference.com/w/cpp/thread/lock_guard

代码示例:未经过测试可能会导致datarace和/或死锁

#include <thread>
#inclue <mutex>
typedef struct
{
    int a;
    double b;

} data;

data glob;
mutex mymutex;

int main()
{

    thread reader([]()
    {
        while(1)
        {
            mymutex.lock();
            sleep(1s);
            cout << glob;
            mymutex.unlock();
        }
    });

    thread writer1([]()
    { 
        while(1)
            mymutex.lock();
            glob.a++;
            mymutex.unlock();
    });
    thread writer2([]()
    { 
        while(1)
            mymutex.lock();
            glob.b++;
            mymutex.unlock();
    });


    int i;
    cin >>i;
}

因此,这会在更改glob时锁定互斥锁,并在互连完成更改后解锁互斥锁。当互斥锁被锁定时,另一个尝试访问该互斥锁的线程将无法执行,因此将等待一段时间,然后再次尝试。最终它会抓住它并能够自己锁定它。然后另一个线程将不得不等待它解锁。

我链接的lock_guard是一种使用互斥锁的更安全的方法,但只能在函数中使用。你把它放在函数的开头,然后它将保持锁定直到函数返回。这意味着您不必确保在函数的每个返回路径上解锁互斥锁,因为这是自动完成的。

Mutex确实存在死锁问题。当您锁定互斥锁,然后在互斥锁解锁之前尝试再次在同一线程中锁定互斥锁时,会发生这种情况。它将永远等待无法解锁,其他线程也无法继续。如果您从互斥区域调用函数,则简单的解决方案是使用多个互斥锁。