0、互斥量
Windows下的互斥量
是個內核對象,每次WaitForSingleObject和ReleaseMutex時都會檢查當前線程ID和占有互斥量的線程ID是否一致。
當多次Wait**時就要對應多次ReleaseMutex, 當ReleaseMutex過多次數時如果發現當前占有互斥量的線程ID和當前調用ReleaseMutex的線程ID不一致時僅僅返回FLASE,GetLastError返回ERROR_NOT_OWNER,沒有其他副作用。
當占有mutex的線程在Release之前退出時,該mutex被【遺棄】,此時系統自動收回mutex,可供其他線程申請。
允許多次等待
WaitForSingleObject(hMutex, time);
WaitForSingleObject(hMutex, itme);
多次等待 對應多次釋放
ReleaseMutex(hMutex);
ReleaseMutex(hMutex);
Linux下的互斥量
可以設置互斥量的屬性是否為可以被同一個線程多次lock, 還可以設置該互斥量的范圍,即是用於進程之間同步 還是 同一進程不同線程之間的同步。
相關API 將說明見代碼注釋部分。
1、相關API
//Initialize a mutex with attribute(can be NULL) int pthread_mutex_init( pthread_mutex_t* mutex, const pthread_mutexattr_t* mutexattr); //lock a mutex int pthread_mutex_lock(pthread_mutex_t* mutex); //ulock a mutex int pthread_mutex_unlock(pthread_mutex_t* mutex); //destroy a mutex int pthread_mutex_destroy(pthread_mutex_t* mutex); int pthread_mutexattr_setpshared( pthread_mutexattr_t* mattr, int pshared //PTHREAD_PROCESS_SHARE | PTHREAD_PROCESS_PRIVATE
); int pthread_mutexattr_getshared( pthread_mutexattr_t* mattr, int* pshared); int pthread_mutexattr_settype( pthread_mutexattr_t* attr, int type //PTHREAD_MUTEX_TIMED_NP -- default value //PTHREAD_MUTEX_RECURISIVE_NP -- allow a thread lock multitimes //PTHREAD_MUTEX_ERRORCHECK_NO -- check error lock, return EDEADLK if the same thread want to LOCK //PTHREAD_MUTEX_ADAPTIVE_NO -- adaptive lock, the simplest lock
) int pthread_mutexattr_gettype( pthread_mutexattr_t* attr, int* type )
2、demo
#include <iostream> #include <pthread.h> #include <unistd.h> #include <errno.h>
using namespace std; /*********************************************** * * Initialize a mutex with attribute(can be NULL) * int pthread_mutex_init( * pthread_mutex_t* mutex, * const pthread_mutexattr_t* mutexattr); * * lock a mutex * int pthread_mutex_lock(pthread_mutex_t* mutex); * * unlock a mutex * int pthread_mutex_unlock(pthread_mutex_t* mutex); * * destroy a mutex * int pthread_mutex_destroy(pthread_mutex_t* mutex); * * int pthread_mutexattr_setpshared( * pthread_mutexattr_t* mattr, * int pshared //PTHREAD_PROCESS_SHARE | PTHREAD_PROCESS_PRIVATE * ); * * int pthread_mutexattr_getshared( * pthread_mutexattr_t* mattr, * int* pshared); * * int pthread_mutexattr_settype( * pthread_mutexattr_t* attr, * int type //PTHREAD_MUTEX_TIMED_NP -- default value * //PTHREAD_MUTEX_RECURISIVE_NP -- allow a thread lock multitimes * //PTHREAD_MUTEX_ERRORCHECK_NO -- check error lock, return EDEADLK if the same thread want to LOCK * //PTHREAD_MUTEX_ADAPTIVE_NO -- adaptive lock, the simplest lock * ) * * * int pthread_mutexattr_gettype( * pthread_mutexattr_t* attr, * int* type * ) * *********************************************/
void* work_thread(void* p) { if (NULL == p) return const_cast<char*>("invalid thread argument"); pthread_mutex_t* pMutex = (pthread_mutex_t*)(p); //current thread ID
pthread_t nThreadID = pthread_self(); int i = 0; while(++ i <= 3) { //lock multi times
pthread_mutex_lock(pMutex); pthread_mutex_lock(pMutex); cout << "Thread " << nThreadID << " is Running! " << endl; //and so unlock multi times
pthread_mutex_unlock(pMutex); pthread_mutex_unlock(pMutex); usleep(1000 * 1); //1 miliseconds
} return const_cast<char*>("------ finish -----------"); } void* work_thread2(void* p) { if (NULL == p) return const_cast<char*>("invalid thread argument"); pthread_mutex_t* pMutex = (pthread_mutex_t*)(p); //current thread ID
pthread_t nThreadID = pthread_self(); int i = 0; while(++ i <= 3) { //if current thread can not enter mutex, //and the function pthread_mutex_trylock will RETURN Immediatly
if ( EBUSY == pthread_mutex_trylock(pMutex)) cout << "Other thread is lock the resouce, i am waiting.." << endl; else { cout << "Thread " << nThreadID << " is Running! " << endl; pthread_mutex_unlock(pMutex); usleep(1000 * 1); //1 miliseconds
} } return const_cast<char*>("------ finish -----------"); } int main() { const size_t nThreadCount = 3; pthread_t threadIDs[nThreadCount]; int nRet = -1; pthread_mutex_t mutex; pthread_mutexattr_t mutexattr; void* pRet = NULL; //thread return value //allow a thread lock multi times
nRet = pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE_NP); nRet = pthread_mutex_init(&mutex, &mutexattr); if (0 != nRet) return -1; for (size_t i = 0; i < nThreadCount - 1; ++ i) { nRet = pthread_create(&threadIDs[i], NULL, work_thread, (void*)(&mutex)); if (0 != nRet) continue; } nRet = pthread_create(&threadIDs[nThreadCount - 1], NULL, work_thread2, (void*)(&mutex)); if (0 != nRet) cerr << endl << "work_thread2 created falied! " << endl; for (size_t i = 0; i < nThreadCount; ++ i) { nRet = pthread_join(threadIDs[i], &pRet); if (0 == nRet) { cout << " Thread " << threadIDs[i] << " Finished ! " \ " It's return value is " << (char*)pRet << endl; } } pthread_mutex_destroy(&mutex); return 0; }
3、執行結果