下面摘录一些关于C++当中
自旋锁(spin lock)与互斥量(mutex)的比较
自旋锁是一种非阻塞锁,也就是说,如果某线程需要获取自旋锁,但该锁已经被其他线程占用时,该线程不会被挂起,而是在不断的消耗CPU的时间,不停的试图获取自旋锁。
互斥量是阻塞锁,当某线程无法获取互斥量时,该线程会被直接挂起,该线程不再消耗CPU时间,当其他线程释放互斥量后,操作系统会激活那个被挂起的线程,让其投入运行。
两种锁适用于不同场景:
如果是多核处理器,如果预计线程等待锁的时间很短,短到比线程两次上下文切换时间要少的情况下,使用自旋锁是划算的。
如果是多核处理器,如果预计线程等待锁的时间较长,至少比两次线程上下文切换的时间要长,建议使用互斥量。
如果是单核处理器,一般建议不要使用自旋锁。因为,在同一时间只有一个线程是处在运行状态,那如果运行线程发现无法获取锁,只能等待解锁,但因为自身不挂起,所以那个获取到锁的线程没有办法进入运行状态,只能等到运行线程把操作系统分给它的时间片用完,才能有机会被调度。这种情况下使用自旋锁的代价很高。
如果加锁的代码经常被调用,但竞争情况很少发生时,应该优先考虑使用自旋锁,自旋锁的开销比较小,互斥量的开销较大。
代码测试:
互斥锁:
#include<stdlib.h>
#include<unistd.h>
#include<stdio.h>
#include<errno.h>
#include<pthread.h>
#include<sys/time.h>
int num = 0;
int count = 100000;
pthread_mutex_t mulock;
long long getSystemTime(){
struct timeval tv;
gettimeofday(&tv, NULL);
return 1000 * 1000 * tv.tv_sec + tv.tv_usec;
}
void* testmutex(void* arg){
(void)arg;
pthread_t thread_id = pthread_self();
printf("this thread id %ld\n", thread_id);
for(int i = 0 ; i < count ; ++i){
pthread_mutex_lock(&mulock);
num++;
pthread_mutex_unlock(&mulock);
}
}
int main()
{
pthread_t tid1;
pthread_t tid2;
tid1 = pthread_self();
printf("this thread is %ld\n", tid1);
long long Start_time = getSystemTime();
pthread_create(&tid2, NULL, testmutex, NULL);
for(int i = 0; i < count; ++i){
pthread_mutex_lock(&mulock);
num++;
pthread_mutex_unlock(&mulock);
}
pthread_join(tid2, NULL);
long long End_time = getSystemTime();
printf("use time is %lld, num is %d\n", End_time - Start_time, num );
pthread_mutex_destroy(&mulock);
return 0;
}
自旋锁:
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<sys/time.h>
#include<stdlib.h>
#include<errno.h>
int num = 0;
int count = 100000;
pthread_spinlock_t splock;
long long getSystemTime(){
struct timeval tv;
gettimeofday(&tv, NULL);
return 1000* 1000 *tv.tv_sec + tv.tv_usec;
}
void* testSpin(void* arg){
(void)arg;
pthread_t thread_id = pthread_self();
printf("this thread is %ld\n", thread_id);
int i = 0;
for(; i < count; ++i){
pthread_spin_lock(&splock);
num++;
pthread_spin_unlock(&splock);
}
}
int main()
{
pthread_t tid1;
pthread_t tid2;
pthread_spin_init(&splock,PTHREAD_PROCESS_PRIVATE );
tid1 = pthread_self();
printf("this thread is %ld\n", tid1);
long long Start_time = getSystemTime();
int ret = pthread_create(&tid2, NULL, testSpin, NULL);
if(ret != 0){
perror("pthread_create");
return -1;
}
for(int i = 0 ; i < count; ++i){
pthread_spin_lock(&splock);
num++;
pthread_spin_unlock(&splock);
}
pthread_join(tid2, NULL);
long long End_time = getSystemTime();
printf("use time %lld, num = %d\n", End_time - Start_time , num);
pthread_spin_destroy(&splock);
return 0;
}
结果: