您的位置:首页 > 运维架构 > Linux

互斥量--linux多线程的运用

2015-12-29 15:37 417 查看
一、什么是互斥量

互斥量是另一种用于多线程中的同步访问方法,它允许程序锁住某个对象,使得每次只能有一个线程访问它。

二、linux下的互斥量函数

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);

int pthread_mutex_lock(pthread_mutex_t *mutex);

int pthread_mutex_unlock(pthread_mutex_t *mutex);

int pthread_mutex_destroy(pthread_mutex_t *mutex); </span>


它们的意义就如它们的名字所示的那样,分别是初始化一个互斥量、对一个互斥量上锁、对一个互斥量解锁。成功时返回0,失败时返回错误代码,它们并不设置errno。

pthread_mutex_init函数中的参数mutexattr指定互斥量的属性,在这里我们并不关心互斥量的属性,所以把它设置为NULL,使用默认属性即可。同样的,pthread_mutex_lock和pthread_mutex_unlock都是原子操作,如果一个线程调用pthread_mutex_lock试图锁住互斥量,而该互斥量,又被其他线程锁住(占用),则该线程的pthread_mutex_lock调用就会阻塞,直到其他线程对该互斥量进行解锁,该线程才能获得该互斥量,pthread_mutex_lock调用才会返回。

注意,使用互斥量的默认属性,如果程序试图对一个已经加锁的互斥量调用pthread_mutex_lock,程序就会阻塞,而又因为拥有互斥量的这个线程正是现在被阻塞的线程,所以这个互斥量就永远不会被解锁,也就是说,程序就会进入死锁的状态。在使用时要多加注意,确保在同一个线程中,对加锁的互斥再次进行加锁前要对其进行解锁。

三、一个简单例子的运用。

本例程中,进程含有两个线程,两个线程分别通过lock和unlock互斥量来相互制约运行,代码如下:

<span style="font-size:18px;">#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>

void *thread_function(void *arg);//线程函数
pthread_mutex_t work_mutex;      //定义一个互斥量

#define WORK_SIZE 1024
char work_area[WORK_SIZE];
int time_to_exit = 0;
int num=0;

int main() {
int res;
pthread_t a_thread;
void *thread_result;
res = pthread_mutex_init(&work_mutex, NULL);
if (res != 0) {
perror("Mutex initialization failed");
exit(EXIT_FAILURE);
}
res = pthread_create(&a_thread, NULL, thread_function, NULL);
if (res != 0) {
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
pthread_mutex_lock(&work_mutex);
printf("lock1\n");
sleep(1);
pthread_mutex_unlock(&work_mutex);
printf("unlock1\n");
sleep(1);

pthread_mutex_lock(&work_mutex);
printf("lock2\n");
sleep(1);
pthread_mutex_unlock(&work_mutex);
printf("unlock2\n");
sleep(1);
pthread_mutex_lock(&work_mutex);

printf("finsh\n");
pthread_mutex_destroy(&work_mutex);

exit(EXIT_SUCCESS);
}

void *thread_function(void *arg) {
while(num<2)
{
pthread_mutex_lock(&work_mutex);
printf("num=%d\n",++num);
printf("wait...");
sleep(5);
pthread_mutex_unlock(&work_mutex);
sleep(1);
}
pthread_exit(0);
}
</span>

程序运行结果如下:



例程解析:
(1).程序(主线程)首先通过pthread_mutex_init函数创建了一个work_mutex互斥量,接着又创建一个thread_function线程,并且thread_function线程一创建后,就进行pthread_mutex_lock互斥量,所以除非主线程有解锁动作(pthread_mutex_unlock),不然thread_function线程就一直停留在此来等待获得锁资源。我们通过主线程和子线程来回解锁两次来观察互斥量的运用,因此设了一个全局变量num来观察。
(2).程序(主线程)创建完thread_function线程后,立马锁将work_mutex互斥量锁住,因此由(1)分析,thread_function线程停留在pthread_mutex_lock(&work_mutex)语句。因此程序(主线程)继续运行打印出lock1,程序(主线程)打印完lock1后,通过pthread_mutex_unlock将互斥量进行解锁,并紧接着打印出unlock1,然后sleep一段时间,这里sleep一段时间,主要是为了给thread_function线程有足够时间获得锁资源。由于程序(主线程)将互斥量解锁释放了,则thread_function线程获得锁资源,因此thread_function线程开始执行,打印出num值,和wait...,并通过sleep停止5s钟。
(3).thread_function线程开始打印出num值至sleep(5)后这段时间,程序(主线程)运行到pthread_mutex_lock(&work_mutex)语句,由于这个时候的锁资源被thread_function线程获得,因此程序(主线程)一直停留在此处,等待获得锁资源。
(4).当thread_function线程sleep(5)后,执行pthread_mutex_unlock(&work_mutex),将锁资源释放然后sleep一段时间,这里sleep一段时间,主要是为了给程序(主线程)有足够时间获得锁资源,则这时程序(主线程)获得锁资源继续运行,而thread_function线程又执行到pthread_mutex_lock(&work_mutex)语句,由于此时锁资源被程序(主线程)获得,所以thread_function线程又停留到此处。
(5).接下去反复(3)、(4)步骤,直至打印出finsh。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: