bool GetLock(bool& x){
if(x){
x= false;
return true;
}
return false;
}
然而,這裏面的讀取和更新不是原子操作的,如果兩個線程同時發現了x是true,但是,還沒有一個線程更新了x,此時,就會有兩個線程同時更新了x,也就是有兩個線程同時更新了鎖的狀態,造成這種原因在於x的讀取和更新不是原子性的。X86裏面有個CMPXCHG 指令,Windows 裏面有個InterLockCompareExchange API都能運行這種原子性的操作,也就是說,我們可以利用這兩個原子操作來完成鎖的實現。以下是代碼
#include <windows.h>
#pragma comment(lib, "kernel32.lib")
class USLock{//user space lock
public:
USLock(){
LockData= new int(1);
}
~USLock(){
delete LockData;
}
public:
bool Get(){
return (InterlockedCompareExchange((LONG*)LockData,0,1));
}
void Release(){
*LockData= 1;
}
private:
int *LockData;
};
DWORD WINAPI CS(void* lpAram);
#include <queue>
#include <iostream>
using namespace std;
deque<int> q;
USLock lock;
int main(){
HANDLE hThread[2];
for(int i= 0; i< 2; ++i){
hThread[i]= ::CreateThread(NULL,0,CS,(void*)i,0,NULL);
}
::WaitForMultipleObjects(2,hThread,true,INFINITE);
}
DWORD WINAPI CS(void* lpAram){
while(true){
if(!lpAram){//生產
for(int i= 0; i< 1000; ){
if(lock.Get()){
q.push_front(i++);
lock.Release();
}
::Sleep(rand()%1000);
}
return 0;
}else{
if(lock.Get()){//消費
if(!q.empty()){
cout<<q.back();
q.pop_back();
}
lock.Release();
}
}
::Sleep(rand()%1000);
}
return 0;
}
後面寫的是一段測試代碼,有興趣的同學可以看看。