【Linux】Mutex互斥量线程同步的例子

时间:2022-09-02 15:11:39

 

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、执行结果

 

【Linux】Mutex互斥量线程同步的例子