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多线程之互斥锁的主要内容,如果未能解决你的问题,请参考以下文章

整数的无锁多线程

并发编程之多线程

25多线程之互斥锁

《C++多线程编程》学习笔记

Python网络编程(进程通信信号线程锁多线程)

无锁多线程编程初步(基础部分)