上一文中简单的说了一下Linux多线程编程的基本操作,这一文来简单的说一说线程之间的同步和互斥。首先说一下多线程之间同步和互斥的基本概念和操作,然后编写一个小例子进行测试。
一、基本概念和操作
由于线程之间对资源和存储空间是共享的,因此对这些资源进行操作和访问时,必须考虑多线程之间的同步和互斥问题。在POSIX中有两种线程的同步机制:互斥锁和信号量。互斥锁比较适用于同时可用资源是唯一的情况,而信号量更适用于同时可用资源为多个的情况。本文重点来说一下互斥锁的使用。
互斥锁常用API说明:
a、初始化一个互斥锁
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)
mutex : 创建一个互斥锁的标识
mutexattr : 创建的互斥锁的属性,主要有三种,分别是: PTHREAD_MUTEX_INITIALIZER,创建快速互斥锁;PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,创建递归互斥锁;PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP,创建检错互斥锁。默认为快速互斥锁。
返回值:0成功,出错返回错误码
b、其他API函数
int pthread_mutex_lock(pthread_mutex_t *mutex,) // 互斥锁上锁
int pthread_mutex_trylock(pthread_mutex_t *mutex,) // 互斥锁判断上锁
int pthread_mutex_unlock(pthread_mutex_t *mutex,) // 互斥锁解锁
int pthread_mutex_destroy(pthread_mutex_t *mutex,) // 销毁互斥锁
mutex :要操作的互斥锁的标识
返回值:0 成功,出错返回错误码。
二、测试
编写一个测试的小例子,实现的功能是:在主线程中创建两个子线程,当其中一个子线程运行完毕时,另一个子线程才开始运行。具体的代码实现如下所示:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
/* 定义一个全局变量用于定义互斥锁 */
static pthread_mutex_t mutex;
/*
* 子线程a的线程体
*/
static void *start_routine_a (void *arg)
{
int loop_cnt = (int)arg;
int i;
pthread_mutex_lock(&mutex); // 进程A上锁
printf("thread A : start!\n");
for(i = 0; i < 5; i++)
{
printf("TECH-PRO thread A : %d\n", i);
sleep(1);
}
printf("thread A : stop!\n");
pthread_mutex_unlock(&mutex); // 进程A释放锁
pthread_exit(NULL); /* 线程执行完毕 */
}
/*
* 子线程b的线程体
*/
static void *start_routine_b (void *arg)
{
int loop_cnt = (int)arg;
int i;
pthread_mutex_lock(&mutex); // 进程B上锁
printf("thread B : start!\n");
for(i = 0; i < 5; i++)
{
printf("TECH-PRO thread B : %d\n", i);
sleep(1);
}
printf("thread B : stop!\n");
pthread_mutex_unlock(&mutex); // 进程B释放锁
pthread_exit(NULL); /* 线程执行完毕 */
}
/*
* 定义两个子线程,让两个子线程同时运行
*/
int main(void)
{
int ret;
pthread_t pthread_a, pthread_b;
/* 初始化这个互斥锁 */
ret = pthread_mutex_init(&mutex, NULL);
if(0 != ret)
{
printf("pthread_mutex_init error!\n");
return -1;
}
/* 开始 */
printf("main : start!\n");
/* 创建两个子线程 */
ret = pthread_create(&pthread_a, NULL, start_routine_a, (void *)5);
if(0 != ret)
{
printf("pthread_create for a is failed!\n");
return -1;
}
ret = pthread_create(&pthread_b, NULL, start_routine_b, (void *)5);
if(0 != ret)
{
printf("pthread_create for b is failed!\n");
return -1;
}
/* 等待进程结束 */
pthread_join(pthread_a, NULL);
pthread_join(pthread_b, NULL);
/* 结束 */
printf("main : stop!\n");
pthread_mutex_destroy(&mutex); // 销毁互斥锁
return 0;
}
对程序进行编译,注意编译和链接时要加上-lpthread,运行结果如下:
从运行结果中可以看出,A线程先运行,等A线程运行结束后B线程才开始运行。