自旋锁相对于原子锁可以实现更为复杂的功能。只能被一个线程持有,如果里面锁已经被持有,后来的就不停忙循环,直到前面的锁被释放,后来者才能进去。
例如:一个房间只有一个钥匙,有人进去喝水了,把钥匙带进去了,你没钥匙就进不去,所以你会不停的敲门,
询问:“有人吗?”,
如果有人,别人就会回答:“有人”。
你不知道里面的人什么时候出来呀,所以你再敲门:“有人吗?”
直到没人为止,你就可以拿着钥匙进去了。
这样就有一个问题:浪费自己的时间(浪费处理器时间),你就在那了不停的敲门,其他神马事情都没做,如果里面的人一直不出来,你就一直敲。
另外一种方案是:里面有人的时候,外面的就休息,出来的时候叫醒你:”hi ,哥们进去吧“(信号量机制,睡眠和唤醒会切换上下文,会带来一部分开销)
ps :自旋锁里面代码的尽量短,尽量可以小于上下文切换的时间
#include "phread.h"
#pragma comment(lib, "pthreadVC2.lib")
volatile long loadNum = 0;
const int threadNum = 51;
pthread_spinlock_t spinLock ;
DWORD WINAPI increment(void *){
pthread_spin_lock(&spinLock);
loadNum++;
pthread_spin_unlock(&spinLock);
return 0;
}
void test(){
pthread_spin_init(&spinLock, 0);
int num = 110;
while(num--){
loadNum = 0;
HANDLE handle[threadNum];
for(int i = 0; i < threadNum; i++){
handle[i] = CreateThread(NULL, 0, increment, NULL, 0, NULL);
}
WaitForMultipleObjects(threadNum, handle, true, INFINITE);
cout << "登陆人数:" << loadNum << endl;
pthread_spin_destory(&spinLock);
}
}
和原子锁的代码基本一样。一定要加库”pthreadVC2.lib“,我刚开始没加,编译没问题,运行是就 报错了:error lnk2001
补充:
1.linux系统里面是不能递归调用自旋锁的,容易 造成死锁。
2.获取锁之前要禁止本地(当前处理器)中断,中断程序可能会打断自旋锁里面的代码(跳转到中断处理程序去了,中断的优先级较高,并且系统允许抢占),锁释放不了,造成死锁,-----------------其他处理器中断,不会影响当前的处理器释放锁。
补充:
读写锁也是比较常见的锁,可以用来优化自旋锁的一些弊端,比如:一本书可以10个人一起看,也不会影响什么,但是只能一个人写,否则,都写就会出现混乱。
设置为读锁的时候,可以并发访问,大大提高了效率,不必让其他读线程傻傻的等。
设置为写锁的时候,只能一个进入,其他还是老老实实在外等着吧。
ps:读锁是可以递归调用的,但是不能和写锁混搭使用(造成死锁)。
const int threadNum = 5;
pthread_rwlock_t rwLock;
DWORD WINAPI increment(void *){
pthread_rwlock_rdlock(&rwLock);
Sleep(100);
cout << "进来读者:" << GetCurrentThreadId() << endl;
Sleep(50);
cout << "结束:" << GetCurrentThreadId() << endl;
pthread_rwlock_unlock(&rwLock);
return 0;
}
void test(){
pthread_rwlock_init(&rwLock,0);
int num = 5;
loadNum = 0;
HANDLE handle[threadNum];
for(int i = 0; i < threadNum; i++){
handle[i] = CreateThread(NULL, 0, increment, NULL, 0, NULL);
}
WaitForMultipleObjects(threadNum, handle, true, INFINITE);
pthread_rwlock_destroy(&rwLock);
}
运行结果:设置为读锁的时候,并行运行,打印结果乱了。
const int threadNum = 5;
pthread_rwlock_t rwLock;
DWORD WINAPI increment(void *){
pthread_rwlock_wrlock(&rwLock);
Sleep(100);
cout << "进来写者:" << GetCurrentThreadId() << endl;
Sleep(50);
cout << "结束:" << GetCurrentThreadId() << endl;
pthread_rwlock_unlock(&rwLock);
return 0;
}
void test(){
pthread_rwlock_init(&rwLock,0);
int num = 5;
loadNum = 0;
HANDLE handle[threadNum];
for(int i = 0; i < threadNum; i++){
handle[i] = CreateThread(NULL, 0, increment, NULL, 0, NULL);
}
WaitForMultipleObjects(threadNum, handle, true, INFINITE);
pthread_rwlock_destroy(&rwLock);
}
运行结果:顺序执行的,一个写锁,只允许一个线程进入。
------------------------------------暂时没搭建linux环境,所以代码采用的是vs2010,win7 上面编译的----------------------------------------------------