Reputation: 685
So in main I have an std::atomic<int>
. It gets sent to a thread that generates random numbers:
void wind_thread(std::atomic<int>* wind)
{
while(total_planes < max_plane )
{
*wind = random(1, 360);
}
}
2 other threads get this variable and do stuff with it, here is an example of one:
void land_thread(std::atomic<int>* wind, std::queue<Plane> *land, Runway *north_south, Runway *east_west)
{
while(total_planes <= max_plane)
{
if(land->size() == 0){}
else
{
std::lock_guard<std::mutex> guard(my_mutex);
std::cout << "Plane " << land->front().get_plane_id()
<< " landed on " << wind_string(wind) << " Wind was: "
<< *wind << std::endl;
land->front().set_details(wind_string(wind));
if((*wind >= 46 && *wind <= 135) || (*wind >= 226 && *wind <= 315))
{
east_west->land(land->front());
land->pop();
}
else
{
north_south->land(land->front());
land->pop();
}
total_planes++;
}
}
}
the wind in the land_thread is fine but when I pass it to that wind_string()
function which takes an std::atomic<int>* x
, it gets a new value.
It works fine if I put a lock on the wind thread, but I thought the whole point of using std::atomic
was that if only one thread is writing to it, I wouldn't need to use a lock. Is it because I'm passing it to a function outside of the thread? I've been looking around online and all I can find is that I shouldn't need the lock. If someone could explain why it behaves like this or has a link that goes a bit more into how atomic behaves, it would be appreciated. Thanks.
Upvotes: 1
Views: 470
Reputation: 433
your wind thread will use an entire thread at 100% usage just to keep your wind random. Add some sleep
s there to avoid unnecessary stress on your CPU or slow downs of your program.
Or consider just generating the random value on demand. (see Why does an empty loop use so much processor time? )
atomic only makes the access to the data itself atomic
if((*wind >= 46 && *wind <= 135) || (*wind >= 226 && *wind <= 315))
still can have wind
changed ON EACH check. You could simply copy the current wind beforehand. Something like:
int currentWind = wind->load();
if((currentWind >= 46 && currentWind <= 135) || (currentWind >= 226 && currentWind <= 315))
Or use a mutex as you did before
Upvotes: 0
Reputation: 62573
Since there is no lock around atomic setting of the wind
, you have absolutely no guarantee that you are going to see a value wind
had at a certain time. All the atomic gives you is that as of the time of setting, this value would be propagated, so that anybody reading it before it is reset will get the set value. It also guarantees anything which is set before this atomic int is set is also going to be visible.
However, in your example, nothing prevents wind
from being modified while you hold the lock in another thread.
Upvotes: 2