C++中关于互斥量的全面认知_第1页
C++中关于互斥量的全面认知_第2页
C++中关于互斥量的全面认知_第3页
C++中关于互斥量的全面认知_第4页
C++中关于互斥量的全面认知_第5页
已阅读5页,还剩3页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第C++中关于互斥量的全面认知目录互斥量(保护对共享变量的访问)1.概念2.状态3.特点互斥量的分配1.静态分配2.动态分配加锁和解锁互斥量1.创建互斥锁2.初始化互斥锁3.获取互斥锁4.阻塞调用5.非阻塞调用6.超时调用7.释放互斥锁8.销毁线程锁互斥量的死锁

互斥量(保护对共享变量的访问)

1.概念

互斥(mutex)是防止同时访问共享资源的程序对象。

为避免线程更新共享变量时所出现问题,必须使用互斥量(mutex是mutualexclusion的缩写)来确保同时仅有一个线程可以访问某项共享资源。即就是使用互斥量来实现原子访问操作

2.状态

已锁定(locked)和未锁定(unlocked)。任何时候,至多只有一个线程可以锁定该互斥量。试图对已经锁定的某一互斥量再次加锁,将可能阻塞线程或者报错失败,具体取决于加锁时使用的方法

3.特点

一旦线程锁定互斥量,随即成为该互斥量的所有者。只有所有者才能给互斥量解锁。因为所有权的关系,有时会使用术语获取(acquire)和释放(release)来替代加锁和解锁。

互斥量的分配

互斥量既可以像静态变量那样分配,也可以在运行时动态创建

1.静态分配

互斥量是属于pthread_mutex_t类型的变量

在使用之前必须对其初始化。

pthread_mutex_tmtx=PTHREAD_MUTEX_INITIALIZER

2.动态分配

intpthread_mutex_init(pthread_mutex_t*restrictmutex,constpthread_mutexattr_t*restrictattr);

参数mutex指定函数执行初始化操作的目标互斥量。

参数attr是指向pthread_mutexattr_t类型对象的指针,该对象在函数调用之前已经过了初始化处理,用于定义互斥量的属性。若将attr参数置为NULL,则该互斥量的各种属性会取默认值。

注:

初始化一个业已初始化的互斥量将导致未定义的行为动态分配于堆中的互斥量。例如,动态创建针对某一结构的链表,表中每个结构都包含一个pthread_mutex_t类型的字段来存放互斥量,借以保护对该结构的访问。互斥量是在栈中分配的自动变量。初始化经由静态分配,且不使用默认属性的互斥量。

加锁和解锁互斥量

初始化之后,互斥量处于未锁定状态。函数pthread_mutex_lock()可以锁定某一互斥量,而函数pthread_mutex_unlock()则可以将一个互斥量解锁。

函数原型

intpthread_mutex_lock(pthread_mutex_t*mutex);

intpthread_mutex_trylock(pthread_mutex_t*mutex);

intpthread_mutex_unlock(pthread_mutex_t*mutex);

intpthread_mutex_timedlock(pthread_mutex_t*restrictmutex,conststructtimespec*restrictabs_timeout);

1.创建互斥锁

pthread_mutex_tmtx;

互斥锁的类型是pthread_mutex_t,所以定义一个变量就是创建了一个互斥锁:

2.初始化互斥锁

//第二个参数为NULL,互斥锁的属性会设置为默认属性

pthread_mutex_init(mtx,NULL);

3.获取互斥锁

在进行互斥操作的时候,应该先拿到锁再执行需要互斥的操作,否则可能会导致多个线程都需要访问的数据结果不一致。

4.阻塞调用

pthread_mutex_lock(mtx);

5.非阻塞调用

如果锁被占用就不用,如果没被占用那就用,可以使用pthread_mutex_trylock()函数。用法和pthread_mutex_lock()用法类似,不过当请求的锁正在被占用的时候,不会进入阻塞状态,而是立刻返回,并返回一个错误代码EBUSY,意思是说,有其它线程正在使用这个锁。

interr=pthread_mutex_trylock(mtx);

if(0!=err){

if(EBUSY==err){

//Themutexcouldnotbeacquiredbecauseitwasalreadylocked.

6.超时调用

如果不想不断的调用pthread_mutex_trylock()来测试互斥锁是否可用,而是想阻塞调用,但是增加一个超时时间,用pthread_mutex_timedlock()解决,其调用方式如下:

structtimespecabs_timeout;

abs_timeout.tv_sec=time(NULL)+1;

abs_timeout.tv_nsec=0;

interr=pthread_mutex_timedlock(mtx,abs_timeout);

if(0!=err){

if(ETIMEDOUT==err){

//Themutexcouldnotbelockedbeforethespecifiedtimeoutexpired.

阻塞等待,但是只等待一秒钟,后如果还没拿到锁的话,那就返回,并返回一个错误代码ETIMEDOUT,意思是超时了。

其中timespec定义在头文件time.h中,其定义如下

structtimespec

__time_ttv_sec;/*Seconds.*/

longinttv_nsec;/*Nanoseconds.*/

这个函数里面的时间,是绝对时间,所以这里用time()函数返回的时间增加了1秒

7.释放互斥锁

用完互斥锁,一定要记得释放,下一个想要获得这个锁的线程,只能去等。

释放互斥锁比较简单,使用pthread_mutex_unlock()即可:

pthread_mutex_unlock(mtx);

8.销毁线程锁

pthread_mutex_destroy(mtx)

一个被销毁的线程锁可以被pthread_mutex_init()再次初始化。对被销毁的线程锁进行其它操作,其结果是未定义的。

对一个处于已初始化但未锁定状态的线程锁进行销毁是安全的。尽量避免对一个处于锁定状态的线程锁进行销毁操作。

互斥量的死锁

当超过一个线程加锁同一组互斥量时,就有可能发生死锁。

例,每个线程都成功地锁住一个互斥量,接着试图对已为另一线程锁定的互斥量加锁。

两个线程将无限期等待

有两种解决方法

1.当多个线程对一组互斥量操作时,总是应该以相同顺序对该组互斥量进行锁定,如果两个线程总是先锁定mutex1再锁定mutex2,死锁就不会出现

2.使用频率较低,就是尝试一下,然后恢复,在这种方案中,线程先使用函数pthread_mutex_lock()锁定第1个互斥量,然后使用函数pthread_mutex_trylock()来锁定其余互斥量。如果任一pthread_mutex_trylock()调用失败(返回EBUSY),那么该线程将释放所有互斥量,也许经过一段时间间隔,从头再试

注:

对共享资源操作前一定要获得锁。完成操作以后一定要释放锁。尽量短时间地占用锁。如果有多锁,如获得顺序是ABC连环扣,释放顺序也应该是ABC。线程错误返回时应该释放它所获得的锁。

例子

保护fp指向文件中数的累加正常进行

staticpthread_mutex_tmut=PTHREAD_MUTEX_INITIALIZER;

void*thr_prime(void*p)

FILE*fp;

charlinebuf[linesize];

fp=fopen(fname,"r+");//多个线程之间相撞拿到同一个fp开始覆盖写操作

if(fp==NULL)

perror("fopen");

exit(-1);

//加锁

pthread_mutex_lock(mut);

fgets(linebuf,linesize,fp);

fseek(fp,0,SEEK_SET);

fprintf(fp,"%d\n",atoi(linebuf)+1);

//解锁

pthread_mutex_unlock(mut);

fclose(fp);

pthread_exit(NULL);

intmain()

interr,i;

pthread_ttid[thrnum];

//main线程进行创建线程

for(i=0;i=thrnum;i++)

err=pthread_create(tid+i,NULL,thr_

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论