首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 操作系统 > UNIXLINUX >

Linux多线程——运用互斥量同步线程

2013-10-08 
Linux多线程——使用互斥量同步线程前文再续,书接上一回,在上一篇文章:Linux多线程——使用信号量同步线程中,

Linux多线程——使用互斥量同步线程
前文再续,书接上一回,在上一篇文章:Linux多线程——使用信号量同步线程中,我们留下了一个如何使用互斥量来进行线程同步的问题,本文将会给出互斥量的详细解说,并用一个互斥量解决上一篇文章中,要使用两个信号量才能解决的只有子线程结束了对输入的处理和统计后,主线程才能继续执行的问题。
一、什么是互斥量
互斥量是另一种用于多线程中的同步访问方法,它允许程序锁住某个对象,使得每次只能有一个线程访问它。为了控制对关键代码的访问,必须在进入这段代码之前锁住一个互斥量,然后在完成操作之后解锁。
二、互斥量的函数的使用
它们的定义与使用信号量的函数非常相似,它们的定义如下:



程序分析:
这个程序的工作流程已经说得非常清楚了,这里先来说说在main函数和线程函数thread_func中while循环中的sleep(1)语句的作用。可能很多人会认为这个sleep(1)是为了让子线程完成其处理和统计功能,所以要让主线程休眠1秒钟来等待子线程的处理统计工作的完成。的确在这里子线程进行的工作十分简单,1秒钟内的确可以处理统计完毕。但是这里的sleep(1)并不是为了实现这个功能,这两个循环中的sleep(1)是为了让其他的线程有机会被执行到,如果在一次的加锁和解锁之间没有这条语句的话,则当前的线程将会一直在循环中获得互斥量,因为其他的线程没有执行它的代码的时间,所以就要用这样的一条语句来给其他的线程一个运行的机会。如果子线程的执行时间超过1秒,这个程序还是会正常运行。
以这个例子来说,在主线程中,当输入数据完毕并对互斥量解锁之后,并不马上循环对其加锁,此时子线程就有了执行的机会,它会对互斥量进行加锁,同样地,当它处理统计完输入的数据后,它在进入下一次循环前,也休眠1秒,让主线程有机会再次运行。而主线程什么时候能够执行,取决于子线程何时对互斥量进行解锁。因为如果子线程拥有(锁住)互斥量,则主线程中函数pthread_mutex_lock就不会返回,使主线程处于阻塞状态。
换句话来说,就是只有子线程结束了对输入的处理和统计后,主线程才能继续执行,向msg中写入数据。看到这里,你应该知道之前在使用信号量时,我们多用一个信号量也是为了达到这个目的。所以当我们输入TEST时,程序有两个输入,但还是能正常运行,同样解决了之前使用一个信号量时所带来的问题。
信号量和互斥量的作用都是保护代码段的互斥设备,它们也非常相似。但在本例中,与使用信号量相比,实现同样的功能,如果使用信号量的话,则需要两个信号量,而使用互斥量的话,只需要一个。可以说在本例中,使用互斥量更简单。但是我觉得使用互斥量更容易犯错,我们可以看到在这个例子中,我们需要使用sleep语句来让其他线程获得执行的机会,但是在使用信号量的程序,它并不需要使用sleep,相对来说比较直观。我知道可能是我的实现方法不好,但是对于使用互斥量来说,我想了很久也想不到不使用sleep的方法。

3楼QQ641187518昨天 22:42
主线程执行while(strcmp("end\n", msg) != 0) 时,子线程可能处于for循环nfor(i = 0; ptr[i] != '\0'; ++i) n { n if(ptr[i] >= 'a' && ptr[i] <='z') n { n ptr[i] -= 'a' - 'A'; n } n } n此时对msg的访问读写冲突!!!互斥并未能保护msg变量,此例子有错误
Re: ljianhui昨天 22:51
回复QQ641187518n感谢你的意见,在主线程中的确有点错误,应该像子线程的while循环那样写!
2楼QQ641187518昨天 22:13
printf("Input some test. Enter 'end' to finish\n"); n while(strcmp("end\n", msg) != 0) n { n //把互斥量mutex加锁,以确保同一时间只有该线程可以访问msg中的数据 nn这句代码strcmp("end\n", msg) != 0中比较msg没被互斥保护吧?正在比较时会不会线程执行到:nfor(i = 0; ptr[i] != '\0'; ++i) n { n if(ptr[i] >= 'a' && ptr[i] <='z') n { n ptr[i] -= 'a' - 'A'; n } n } nn线程创建后,我们并不知道主线程执行到strcmp时子线程会不会恰好执行到上面的for循环,此时可能访问冲突
1楼QQ641187518昨天 22:03
主线程执行while(strcmp("end\n", msg) != 0) 时,子线程可能处于for循环nfor(i = 0; ptr[i] != '\0'; ++i) n { n if(ptr[i] >= 'a' && ptr[i] <='z') n { n ptr[i] -= 'a' - 'A'; n } n } n此时对msg的访问读写冲突!!!
Re: ljianhui昨天 22:14
回复QQ641187518n我修改了一下代码,你看一下,还有没有错误,谢谢

热点排行