25多线程之互斥锁
Posted gd-luojialin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了25多线程之互斥锁相关的知识,希望对你有一定的参考价值。
例子:利用两个子进程从50进行降序输出
int g_num=50;
//偶数
void *threadEven(void *lParam)
{
while(g_num>0)
{
if(!(g_num&1))
{
printf("even:%d ",g_num);
}
g_num--;
usleep(1);
}
return NULL;
}
//奇数
void *threadOdd(void *lParam)
{
while(g_num>0)
{
if(g_num&1)
{
printf("odd:%d ",g_num);
}
g_num--;
usleep(1);
}
return NULL;
}
void testMutex()
{
pthread_t thread1,thread2;
int nRet1=pthread_create(&thread1,NULL,threadOdd,NULL);
int nRet2=pthread_create(&thread2,NULL,threadEven,NULL);
printf("thread1 id:%d thread2 id:%d ",(int)thread1,(int)thread2);
if(nRet1||nRet2)
{
fprintf(stderr,"fail to create thread!");
return ;
}
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
}
int main(int argc,char**argv)
{
testMutex();
return 0;
}
上面的代码表示,创建两个子进程,子进程threadOdd输出奇数,子进程threadEven输出偶数。并且奇偶数是交替输出。即从50降序输出。
如果实现奇偶数分开输出,如:先把50内的奇数或偶数输出。此时就要加锁。
线程互斥
多线程共享进程资源,访问共享资源时候,需要进行互斥操作确保数据的有效性
什么是锁操作:
比如:两人进屋子拿东西,A先进去反锁屋子,那么B就进不去。只有等A开锁出来后,才轮到B进去。
锁类型设置/获取
int pthread_mutexattr_settype(pthread_mutexattr_t* attr, int type);
int pthread_mutexattr_gettype(pthread_mutexattr_t* attr, int *type);
type参数:
mutex 锁类型 PTHREAD_MUTEX_XXX
NORMAL: 普通锁,不提供死锁检测,可能出现死锁
ERRORCHECK: 检错锁,同一线程对已锁的互斥锁加锁会返回错误
RECURSIVE: 嵌套锁,允许同一线程多次锁定而不产生死锁,多次释放才能被别的线程锁定
DEFAULT: 默认为普通锁,排队获取锁
创建互斥锁
pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *attr)
注意:
attr == NULL 初始化的线程锁 mutex
等价于 mutex = PTHREAD_MUTEX_INITIALIZER
互斥锁加锁
pthread_mutex_lock(pthread_mutex_t *mutex)
对互斥锁加锁
同一线程内对已经加锁的互斥锁,进行再次加锁,会造成死锁
互斥锁解锁
pthread_mutex_unlock(pthread_mutex_t *mutex)
释放互斥锁
对未锁定的互斥锁,进行释放操作,会产生不确定的行为
尝试解除有其他线程创建的互斥锁,会产生不确定的行为
pthread_mutex_trylock(pthread_mutex_t *mutex)
试图锁住互斥体,不阻塞
1: 互斥体未上锁,锁定并返回成功
2: 互斥体已经上锁,不阻塞直接返回失败
3: 锁类型为嵌套锁 RECURSIVE, 已上锁,则锁计数器自加
问题:若使用man无法查询文档?pthread_mutex_* 函数族 man 无显示解决办法
解决方式:$ sudo apt-get install manpages-posix-dev
例子:利用互斥锁,两个子进程分开输出50的奇偶数
pthread_mutex_t mutex;
int g_num=50;
void *threadEven(void *lParam)
{
//加锁
pthread_mutex_lock(&mutex);
while(g_num>0)
{
if(!(g_num&1))
{
printf("even:%d ",g_num);
}
g_num--;
usleep(1);
}
g_num=50;
//解锁
pthread_mutex_unlock(&mutex);
return NULL;
}
void *threadOdd(void *lParam)
{
//加锁
pthread_mutex_lock(&mutex);
while(g_num>0)
{
if(g_num&1)
{
printf("odd:%d ",g_num);
}
g_num--;
usleep(1);
}
g_num=50;
//解锁
pthread_mutex_unlock(&mutex);
return NULL;
}
void testMutex()
{
pthread_t thread1,thread2;
//初始化互斥锁
pthread_mutex_init(&mutex,NULL);
int nRet1=pthread_create(&thread1,NULL,threadOdd,NULL);
int nRet2=pthread_create(&thread2,NULL,threadEven,NULL);
printf("thread1 id:%d thread2 id:%d ",(int)thread1,(int)thread2);
if(nRet1||nRet2)
{
fprintf(stderr,"fail to create thread!");
return ;
}
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
}
int main(int argc,char**argv)
{
testMutex();
return 0;
}
以上是实现,奇偶数分开输出。
ERRORCHECK和RECURSIVE属性:
例子:锁上加锁,ERRORCHECK错误返回
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
pthread_mutex_t mutex;
int g_num=50;
//验证死锁
void *thread()
{
int nRet=pthread_mutex_lock(&mutex);
if(nRet)
{
printf("repeat lock! ");
return NULL;
}
printf("test:%d ",g_num);
pthread_mutex_unlock(&mutex);
return NULL;
}
void *threadEven(void *lParam)
{
int nRet=pthread_mutex_lock(&mutex);
if(nRet)
{
printf("repeat lock! ");
return NULL;
}
while(g_num>0)
{
if(!(g_num&1))
{
printf("even:%d ",g_num);
}
g_num--;
usleep(1);
}
g_num=50;
thread();
pthread_mutex_unlock(&mutex);
return NULL;
}
void *threadOdd(void *lParam)
{
int nRet=pthread_mutex_lock(&mutex);
if(nRet)
{
printf("repeat lock! ");
return NULL;
}
while(g_num>0)
{
if(g_num&1)
{
printf("odd:%d ",g_num);
}
g_num--;
usleep(1);
}
g_num=50;
thread();
pthread_mutex_unlock(&mutex);
return NULL;
}
void testMutex()
{
pthread_t thread1,thread2;
pthread_mutexattr_t attr;
//设置锁的属性
//pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_ERRORCHECK);
//默认排队锁
//pthread_mutex_init(&mutex,NULL);
pthread_mutex_init(&mutex,&attr);
int nRet1=pthread_create(&thread1,NULL,threadOdd,NULL);
int nRet2=pthread_create(&thread2,NULL,threadEven,NULL);
printf("thread1 id:%d thread2 id:%d ",(int)thread1,(int)thread2);
if(nRet1||nRet2)
{
fprintf(stderr,"fail to create thread!");
return ;
}
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
}
int main(int argc,char**argv)
{
testMutex();
return 0;
}
以上是关于25多线程之互斥锁的主要内容,如果未能解决你的问题,请参考以下文章