Reputation: 14869
I am experimenting the atomic_compare_and_swap
function to do a basic lock on a std::atomic<bool>
.
The behaviour I was expecting is that the second thread i.e Consume
would remain blocked in the while
loop at the beginning of Access::get()
for all the time the atomic lock_
is set to true
.
Due to the sleeps
I've introduced it is always the first thread Produce
to set the atomic to true
to prevent the second thread to proceed.
Unfortunately this is not the case and I can see that the second thread executes immediately and doesn't remain blocked at all.
What am I doing wrong?
I am using g++4.9 on Lubuntu
class Access
{
atomic<bool> lock_;
bool UNLOCKED_;
public:
Access() : lock_(false), UNLOCKED_(false){}
void set()
{
// lock
while(!atomic_compare_exchange_strong(&lock_, &UNLOCKED_, true)) {}
this_thread::sleep_for(std::chrono::seconds(20));
cout << "set" << endl;
}
void get()
{
// lock
while(!atomic_compare_exchange_strong(&lock_, &UNLOCKED_, true)){}
cout << "get" << endl;
}
};
Access gTest; // global
void Produce() { gTest.set(); }
void Consume() { gTest.get(); }
int main() {
thread producer(Produce);
this_thread::sleep_for(std::chrono::seconds(3));
thread consumer(Consume);
producer.join();
consumer.join();
return 0;
}
Upvotes: 0
Views: 744
Reputation: 3082
When the producer thread executes set()
and the CAS loop, it will see that the value of UNLOCKED_
and lock_
are the same (false
), sets lock_
to true, and returns true. Thus,the loop exits and this thread waits for 20 seconds.
At the same time, the 3 second delay you imposed with
this_thread::sleep_for(std::chrono::seconds(3));
in main() is still ticking and when it expires, the consumer thread executes get()
and the CAS loop will first see that UNLOCKED_
is false
but lock_
is true (because it was set by the producer), and so it updates the value of UNLOCKED_
to true
and spins again. On the next iteration of the CAS loop, it will see that both lock_
and UNLOCKED_
are now true
(UNLOCKED_
was set in the previous iteration), and the loop breaks out.
Upvotes: 2