I have 2 threads, A and B. Thread A want to let B know how many records of data it has received. In modern C , we can use Atomic or CAS or Mutex to modify the counter. How ever, neither of them is fast enough for me.
I am thing about, use a int64_t without a lock to share data counter between threads. Only thread A can modify it, other threads can only read it. I don't know whether it is safe to do so.
I know in x86-64 machines, a 64 bit int can be written with one single asm store
. So I think it should be safe. And I write the following code to check it. If the method is not safe, cnt will not always increase because we will read wrong values from that 64bit memory.
#include <iostream>
#include <vector>
#include <thread>
using namespace std;
int main() {
int64_t cnt = 0;
vector<thread> threadVec;
for (int i=0; i<10; i ){
threadVec.emplace_back(move(thread([&cnt](){
int64_t prev = 0, tmp = 0;
while(prev != INT64_MAX){
tmp = cnt;
// If it is not safe, tmp will not increase all the time.
if (tmp < prev) cout << "Error cnt declined" << endl;
// if (tmp % 1000000 == 0) cout << tmp << endl;
prev = tmp;
}
})));
}
this_thread::sleep_for(chrono::seconds(1));
while(cnt < INT64_MAX) cnt ;
for (auto& t : threadVec)
t.join();
return 0;
}
So is the idea correct?
CodePudding user response:
No, it's undefined behavior.
Make it a std::atomic<int64_t>
, instead. This is what std::atomic
is for.