Reputation: 119
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?
Upvotes: 2
Views: 1249
Reputation: 377
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/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. 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. 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.
Upvotes: 0
Reputation: 1528
#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.
Upvotes: 4