简体   繁体   English

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

[英]Multithread data synchronisation in C++

Here is my questions. 这是我的问题。 I have several threads which modify the attributs of a struture, and I have a thread who read the structure. 我有几个线程可以修改结构的属性,还有一个线程可以读取结构。 How can I be sure that the value I'm reading is not changing by other threads? 如何确定正在读取的值没有被其他线程更改? In my case, a attribut can only be modified by one thread. 就我而言,属性只能由一个线程修改。

Exemple: 例:

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;
}

Then , How can I be sure that when I read glob, it is not being modified by writer1 and writer2? 然后,如何确定当我读取glob时,writer1和writer2没有对其进行修改?

#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;
}

This is a simple working solution to your problem using <atomic> for non-divisible access and write operations. 这是使用<atomic>进行不可分割的访问和写入操作的问题的简单可行解决方案。

Use a mutex it's extremely simple once you get your head around it. 使用互斥锁后,就很简单了。

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

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

code example: not tested may result in datarace and/or deadlock 代码示例: 未经测试可能会导致数据争用和/或死锁

#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;
}

so this will lock the mutex when changing glob, and unlock the mutex when it's finished changing. 因此这将在更改glob时锁定互斥锁,并在完成更改后将其解锁。 When the mutex is locked, another thread trying to access that mutex won't be able to, so will wait for a bit, then try again. 互斥锁被锁定后,另一个试图访问该互斥锁的线程将无法访问,因此将稍等片刻,然后重试。 eventually it will catch it and be able to lock it itself. 最终它将捕获并能够将其自身锁定。 Then the other thread will have to wait for it to unlock. 然后另一个线程将不得不等待它解锁。

the lock_guard that I linked is a safer way to use your mutex, but only works in functions. 我链接的lock_guard是使用互斥锁的一种更安全的方法,但仅适用于函数。 You put it at the start of a function, and then it will stay locked until the function returns. 您将其放在函数的开头,然后它将保持锁定状态,直到函数返回为止。 This means you don't have to ensure you unlock the mutex on every return path of the function as that is done automatically. 这意味着您不必确保在函数的每个返回路径上都解锁互斥锁,因为这是自动完成的。

Mutex's do have a problem of deadlocks. 互斥锁确实存在死锁问题。 This happens when you lock a mutex, then attempt to lock the mutex again in the same thread, before the mutex has unlocked. 当您锁定互斥锁,然后在互斥锁解锁之前尝试在同一线程中再次锁定互斥锁时,会发生这种情况。 It will then wait forever unable to unlock, and the other threads also can't continue. 然后它将永远等待无法解锁,其他线程也无法继续。 Easy solution is to use multiple mutexs if you are calling functions from a mutexed area. 如果要从互斥区域调用函数,则简单的解决方案是使用多个互斥体。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM