POSIX线程同步篇2
用互斥量进行同步
参与Helper2416开发板助学计划心得
什么是互斥量(互斥锁)
如果不需要信号量的计数能力,有时可以使用信号量的一个简化版本,称为互斥量(mutex)。互斥量仅仅适用于管理共享资源或一小段代码。由于互斥量在实现时既容易又有效,这使得互斥量在实现用户空间线程包时非常有用。
互斥量是一个可以处于两态之一的变量:解锁和加锁。这样,只需要一个二进制位表示它,不过实际上,常常使用一个整型量,0表示解锁,而其他所有的值则表示加锁。互斥量使用两个过程。当一个线程(或进程)需要访问临界区时,它调用pthread_mutex_lock。如果该互斥量当前是解锁的(即临界区可用),此调用成功,调用线程可以自由进入该临界区。
另一方面,如果该互斥量已经加锁,调用线程被阻塞,直到在临界区中的线程完成并调用pthread_mutex_unlock。如果多个线程被阻塞在该互斥量上,将随机选择一个线程并允许它获得锁。
pthread互斥量函数
用于互斥量的基本函数和用于信号量的函数非常相似,定义如下:
intpthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t*mutexattr);
intpthread_mutex_lock(pthread_mutex_t *mutex);
intpthread_mutex_unlock(pthread_mutex_t *mutex);
intpthread_mutex_destroy(pthread_mutex_t *mutex);
pthread_mutex_init
函数原型:intpthread_mutex_init(pthread_mutex_t *mutex,
constpthread_mutexattr_t *mutexattr);
函数功能:初始化互斥量。
函数返回:调用成功返回0。
参数说明:
第一个参数mutex,指定互斥量对象。
第二个参数mutexattr,指定了新建互斥量的属性。如果参数attr为空,则使用默认的互斥锁属性,默认属性为快速互斥量。但是通常并不需要这些属性,所以正常做法是指定NULL。
thread_mutex_lock
函数原型:intpthread_mutex_lock(pthread_mutex_t *mutex);
函数功能:锁定互斥对象。
函数返回:调用成功返回0。
参数说明:mutex,接受一个指向互斥对象的指针作为参数以将其锁定。如果碰巧已经锁定了互斥对象,调用者将进入睡眠状态。函数返回时,将唤醒调用者(显然)并且调用者还将保留该锁。
pthread_mutex_unlock
函数原型:intpthread_mutex_unlock(pthread_mutex_t *mutex);
函数功能:把线程已经加锁的互斥对象解锁。
函数返回:调用成功返回0。
参数说明:mutex,指定互斥量对象。始终应该尽快对已加锁的互斥对象进行解锁(以提高性能)。并且绝对不要对您未保持锁的互斥对象进行解锁操作(否则,pthread_mutex_unlock()调用将失败并带一个非零的EPERM返回值)。
pthread_mutex_destroy
函数原型:intpthread_mutex_destroy(pthread_mutex_t *mutex);
函数功能:用完互斥量后对它进行清理。
函数返回:调用成功返回0。
参数说明:mutex,指向要销毁的互斥锁对象。
代码实践
- #include <pthread.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
-
- void *pthread1(void *arg);
- void *pthread2(void *arg);
-
- pthread_mutex_t work_mutex;
- int run_flag = 0;
-
- int main()
- {
- pthread_t thread_id1,thread_id2;
- void *thread_result1, *thread_result2;
- int res;
-
- res = pthread_mutex_init(&work_mutex,NULL);
- if(res != 0){
- perror("mutex initialization failed ...\n");
- exit(EXIT_FAILURE);
- }
-
- res = pthread_create(&thread_id1,NULL,pthread1,NULL);
- if(res != 0){
- perror("pthread1 is not created ...\n");
- exit(EXIT_FAILURE);
- }
-
- res = pthread_create(&thread_id2,NULL,pthread2,NULL);
- if(res != 0){
- perror("pthread2 is not created ...\n");
- exit(EXIT_FAILURE);
- }
-
- res = pthread_join(thread_id1,&thread_result1);
- if(res != 0){
- perror("pthread1 join failed ...\n");
- exit(EXIT_FAILURE);
- }
-
- res = pthread_join(thread_id2,&thread_result2);
- if(res != 0){
- perror("pthread2 join failed ...\n");
- exit(EXIT_FAILURE);
- }
-
- printf("the pthread1 return %s\n",(char *)thread_result1);
- printf("the pthread2 return %s\n",(char *)thread_result2);
-
- pthread_mutex_destroy(&work_mutex);
- return 0;
- }
-
-
- void *pthread1(void *arg)
- {
- int i;
- for(i=0;i<5;i++){
- pthread_mutex_lock(&work_mutex);
- printf("hello this is pthread1 --> %d\n",i);
- pthread_mutex_unlock(&work_mutex);
- sleep(2);
- }
- pthread_exit("pthread1 finished ...\n");
- }
-
- void *pthread2(void *arg)
- {
- int i;
- for(i=0;i<5;i++){
- pthread_mutex_lock(&work_mutex);
- printf("hello this is pthread2 --> %d\n",i);
- pthread_mutex_unlock(&work_mutex);
- sleep(2);
- }
- pthread_exit("pthread2 finished ...\n");
- }
运行结果
- [yuanlai@fedora pthread]$ ./pthread2
- hello this is pthread2 --> 0
- hello this is pthread1 --> 0
- hello this is pthread2 --> 1
- hello this is pthread1 --> 1
- hello this is pthread2 --> 2
- hello this is pthread1 --> 2
- hello this is pthread2 --> 3
- hello this is pthread1 --> 3
- hello this is pthread2 --> 4
- hello this is pthread1 --> 4
- the pthread1 return pthread1 finished ...
-
- the pthread2 return pthread2 finished ...
-
- [yuanlai@fedora pthread]$
得到的实验现象与使用信号量的结果时一样的,暂时还没能找到好些的方式来体现出互斥量的特性,初学理解的还不够透彻,这里只是简单记录该怎么使用互斥量。
二值信号量与互斥量的区别
互斥量必须是在同一个任务申请,同一个任务释放,其他任务释放无效。
二值信号量,一个任务申请后,可以由其他任务释放。
论坛ID:yuanlai2010
发表时间:2014-09-12
本帖最后由 yuanlai2010 于 2014-9-12 13:07 编辑