下面的代码用 atomic 和 lock 分别实现了线程安全的计数器, 可以看到 atomic 的性能比 lock 提升了数十倍.
正常开发中可以使用C++ 标准库中的 atomic, 具有更高的性能, 比 lock 高百倍.
另外, 标准库中的 atomic_flag 也可以当做自旋锁来使用.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| #include <iostream> #include <thread> #include <unistd.h> #include <atomic> #include <sys/time.h>
const int iter_num = 100000; const int thread_num = 3;
int g_count = 0;
std::atomic<bool> atomic_lock(false); std::mutex mtx;
void unsafe_worker() { for (int i = 0; i < iter_num; ++i) { ++g_count; } }
/** * 可以用 atomic<int> 轻易地实现线程安全的计数器, * 这里用 atomic 实现自旋锁, 主要是为了和 lock 做对比 */ void atomic_worker() { for (int i = 0; i < iter_num; ++i) { bool expected = false; // 自旋锁 do { expected = false; } while (!atomic_lock.compare_exchange_weak(expected, true)); ++g_count; atomic_lock.store(false); } }
void lock_worker() { for (int i = 0; i < iter_num; ++i) { std::unique_lock<std::mutex> lock(mtx); ++g_count; } }
void run(std::function<void()> worker) { g_count = 0; std::thread threads[thread_num]; for (int i = 0; i < thread_num; ++i) { threads[i] = std::thread(worker); } for (int i = 0; i < thread_num; ++i) { threads[i].join(); } }
int main() { timeval start_time = (struct timeval) {0}; timeval end_time = (struct timeval) {0}; long interval = 0;
int expected = iter_num * thread_num;
run(unsafe_worker); std::cout << "g_count = " << g_count << ", expected : " << expected << std::endl;
gettimeofday(&start_time, NULL); run(atomic_worker); gettimeofday(&end_time, NULL); interval = ((end_time.tv_sec - start_time.tv_sec) * 1000 * 1000 + (end_time.tv_usec - start_time.tv_usec)); std::cout << "g_count = " << g_count << ", expected : " << expected << ", interval : " << interval << std::endl;
gettimeofday(&start_time, NULL); run(lock_worker); gettimeofday(&end_time, NULL); interval = ((end_time.tv_sec - start_time.tv_sec) * 1000 * 1000 + (end_time.tv_usec - start_time.tv_usec)); std::cout << "lock_g_count = " << g_count << ", expected : " << expected << ", interval : " << interval << std::endl;
return 0; }
|