测量Mutex和Busy等待的效率

该程序将创建多个线程,其中每个线程使用for循环将共享变量增加10000,在每次迭代中将其递增1。 需要互斥锁和自旋锁(忙等待)版本。 据我所知,互斥版本应该比自旋锁更快。 但我实施的内容给了我一个相反的答案……

这是互斥锁版本中每个线程的实现:

void *incr(void *tid) { int i; for(i = 0; i < 10000; i++) { pthread_mutex_lock(&the_mutex); //Grab the lock sharedVar++; //Increment the shared variable pthread_mutex_unlock(&the_mutex); //Release the lock } pthread_exit(0); } 

这是自旋锁版本中的实现:

 void *incr(void *tid) { int i; for(i = 0; i < 10000; i++) { enter_region((int)tid); //Grab the lock sharedVar++; //Increment the shared variable leave_region((int)tid); //Release the lock } pthread_exit(0); } void enter_region(int tid) { interested[tid] = true; //Show this thread is interested turn = tid; //Set flag while(turn == tid && other_interested(tid)); //Busy waiting } bool other_interested(int tid) //interested[] is initialized to all false { int i; for(i = 0; i < tNumber; i++) if(i != tid) if(interested[i] == true) //There are other threads that are interested return true; return false; } void leave_region(int tid) { interested[tid] = false; //Depart from critical region } 

我还迭代了线程创建和运行数百次的过程,以确保可以区分执行时间。 例如,如果tNumber为4,并且我将程序重复1000次,则互斥锁将花费2.22秒,旋转锁定将花费我1.35秒。 随着tNumber的增加,差异会增大。 为什么会这样? 我的代码错了吗?

enter_regionleave_region之间的代码不受保护。

你可以通过使它变得更加复杂来certificate这一点,以确保它会自行解决。

创建一个bool(check)数组,长度10000设置为false。 在enter和leave之间创建代码:

 if (check[sharedVar]) cout << "ERROR" << endl; else check[sharedVar++] = true; 

速度的“差异”在于您正在使用实现同步

 interested[tid] = true; //Show this thread is interested turn = tid; //Set flag while(turn == tid && other_interested(tid)); 

这是顺序操作。 任何线程在执行此操作时都可以被抢占,并且下一个线程会读取错误状态。

它需要通过实现compare-and-swaptest-and-set以primefaces方式完成。 这些说明通常由硬件提供。

例如,在x86上你有xchg, cmpxchg/cmpxchg8b, xadd
您的测试可以重写为

 while( compare_and_swap_atomic(myid,id_meaning_it_is_free) == false); 

问题在于primefaces性很昂贵