【效率对比】c++多线程同步几种方式的效率对比研究: 原子操作,c++锁,自旋锁,windows临界区,windows互斥对象

通过比较以下几种同步方式,测试各方法效率,分为以下6种情况做对比:

  1. 不加任何同步措施;
  2. Windows原子操作;
  3. c++11 mutrex;
  4. 自定义的自旋锁CLCS;
  5. Windows临界区;
  6. Windows互斥对象;

硬件平台:AMD 8核16线程,内存16GB
系统/软件平台:windows10,vs2019com(vc++);
方法:定义3个变量,在多线程中自加(16线程x10万次),记录时间并考察结果正确性;

结果如下:
在这里插入图片描述
结论 :

  1. 不加锁,速度极快,但结果是不可预测的错误值,没有应用价值。
  2. windows原子操作 及 c++11中的mutrex效率非常高;
    【让人不可思议的是,c++的mutrex锁的实现效率非常高,接近了原子操作的效率,这一点非常让人意外,一直以为c++锁会由于跨平台要求和底层调用封装,而会慢于windows临界区,看来这是不
    对的。通过查看mutrex在windows vc 上面的底层实现,发现原来是使用了windows7才加入 SRWLock锁(读写锁),也就是在windows vista及以前的windwos平台仍然使用的临界区,而windows7平台用SRWLock锁替代了,而进一步剖析SRWLock的底层实现,仍然是用的原子自旋锁,这也解释了为什么c++mutrex在win7及以上的平台效率和原子锁效率相同的原因】
  3. 自定义的自旋锁,速度可以实现得很精简,效率略高于Windows临界区的效率,毕竟摆脱了一些多余的调用过程;
  4. Windows临界区效率尚可,但仍然是原子操作和c++锁的所需时间的10倍以上;
  5. Windows互斥对象,由于实现跨进程同步,需要进入系统内核进行调度,所以比较慢,耗时是临界区的10倍以上;

以下是测试代码:
并行化支持

int main() {
   	
	const size_t times = 100000;
	size_t a = 0, b = 0, c = 0;
	CLAtomic<size_t> aa = 0, ba = 0, ca = 0; //原子对象
	CLCS cs;
	CLCSLock cs2;
	TaskPoolStatic volatile as;
	CLTick tk; //高精度定时器
	tk.timingStart();
	parallel_proc([&](int ci, int n) {
     //并行化
		for (size_t i = 0; i < times; i++)
		{
   
			++a; ++b; ++c;
		}
		});
	auto s0_ = tk.getSpendTime();
	cout << "\nno lock:       " << a << " , " << b << " , " << c << " , time = " << s0_ << " , error ...";
	tk.timingStart();
	parallel_proc([&](int ci, int n) {
   
		for (size_t i = 0; i < times; i++)
		{
   
			++aa;++ba;++ca;
		}
		});
	auto s0 = tk.getSpendTime();
	cout << "\nAtomic:        " << aa() << " , " << ba() << " , " << ca() << " , time = " << s0;
	a = 0, b = 0, c = 0;
	mutex cs3;
	tk.timingStart();
	parallel_proc([&](int ci, int n) {
   
		for (size_t i = 0; i < times; i++)
		{
   
			cs3.lock(); ++a; cs3.unlock();
			cs3.lock(); ++b; cs3.unlock();
			cs3.lock(); ++c; cs3.unlock();
		}
		});
	auto s4 = tk.getSpendTime();
	cout << "\nc++11 mutex:   " << a << " , " << b << " , " << c << " , time = " << s4;
	a = 0, b = 0, c = 0;
	tk.timingStart();
	parallel_proc([&](int ci, int n) {
   
		for (size_t i = 0; i < times; i++)
		{
   
			cs.lock(); ++a; cs.unlock();
			cs.lock(); ++b; cs.unlock();
			cs.lock(); ++c; cs.unlock();
		}
		});
	auto s1 = tk.getSpendTime();
	cout << "\nclcs:          " << a << " , " << b << " , " << c << " , time = " << s1;
	a = 0, b = 0, c = 0;
	tk.timingStart();
	parallel_proc([&](int ci, int n) {
   
		for (size_t i = 0; i < times
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值