多线程编程之自旋锁,读写锁

来源:互联网 发布:破解机器码注册软件 编辑:程序博客网 时间:2024/06/05 19:12

自旋锁相对于原子锁可以实现更为复杂的功能。只能被一个线程持有,如果里面锁已经被持有,后来的就不停忙循环,直到前面的锁被释放,后来者才能进去。

例如:一个房间只有一个钥匙,有人进去喝水了,把钥匙带进去了,你没钥匙就进不去,所以你会不停的敲门,

询问:“有人吗?”,

如果有人,别人就会回答:“有人”。

你不知道里面的人什么时候出来呀,所以你再敲门:“有人吗?”

直到没人为止,你就可以拿着钥匙进去了。

这样就有一个问题:浪费自己的时间(浪费处理器时间),你就在那了不停的敲门,其他神马事情都没做,如果里面的人一直不出来,你就一直敲。

另外一种方案是:里面有人的时候,外面的就休息,出来的时候叫醒你:”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 上面编译的----------------------------------------------------

0 0
原创粉丝点击