互斥以排他方式防止共享数据被并发修改。互斥量从本质来说是一把锁,是一个二元变量,其状态为开锁(允许0)和上锁(禁止1),在访问共享资源前对互斥量进行设置(加锁),在访问完成后释放(解锁)互斥量。
(1)在访问该资源前,首先申请该互斥锁,如果该互斥锁处于开锁状态,则申请到该锁对象,并立即占有该锁(使该锁处于锁定状态),以防止其他线程访问该资源;如果该互斥量处于锁定状态,默认阻塞等待
(2)只有锁定该互斥锁的进程才能释放该互斥锁。其他线程的释放操作无效。
在使用互斥锁之前,需要定义该互斥锁(全局变量)。
pthread_mutex_t lock;
#include
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
int pthread_mutex_destory(pthread_mutex_t *mutex);
//两个函数的返回值:若成功,返回0;否则,返回错误编号
第二个参数mutexattr是指向属性对象的指针,该属性对象定义要初始化的互斥锁的属性。如果该指针为NULL,则使用默认属性。
此外,还可以使用宏PTHREAD_MUTEX_INITIALIZER初始化静态分配的互斥锁。
#define PTHREAD_MUTEX_INITIALIZER { { 0, }}
对于静态初始化的互斥锁,不需要调用pthread_mutex_init()函数。
pthread_mutex_t_mp = PTHREAD_MUTEX_INITIALIZER;
如果一个线程要占有一共享资源,其必须先给互斥锁上锁。pthread_mutex_lock()函数以阻塞方式申请互斥锁。
#include
int pthread_mutex_lock(pthread_mutex_t *mutex); //若成功,返回0;否则,返回错误编号
#include
int pthread_mutex_trylock(pthread_mutex_t *mutex); //若成功,返回0;否则,返回错误编号
#include
int pthread_mutex_unlock(pthread_mutex_t *mutex); //若成功,返回0;否则,返回错误编号
下面是一个使用互斥锁的应用实例,在此程序中,共用两个线程: 一个线程负责从标准输入设备中读取数据存储在全局数据区,另一个线程负责将读入的数据输出到标准输出设备。
(1)处理输入操作的线程在接收用户输入信息时不能被中断,因此需要先使用互斥锁获得资源占用,阻塞其他线程的执行。
(2)输出线程中为了保证输出不被中断,同样在输出信息前后需要先锁定互斥锁,操作完成后释放互斥锁。
#include
#include
#include
#include
#include
#define WORK_SIZE 1024
void *thread_function(void *arg);
pthread_mutex_t work_mutex; //全局互斥锁对象
char work_area[WORK_SIZE]; //全局共享数据区
int time_to_exit = 0;
int main(int argc, char *argv[])
{
pthread_t a_thread;
int res;
void *thread_result;
res = pthread_mutex_init(&work_mutex, NULL); //初始化互斥量
if (res != 0)
{
printf("Mutex initialization failed");
exit(EXIT_FAILURE);
}
res = pthread_create(&a_thread, NULL, (void *)thread_function, NULL); //创建新线程
if (res != 0)
{
printf("Thread creation failed");
exit(EXIT_FAILURE);
}
pthread_mutex_lock(&work_mutex); //接收输入前,给互斥锁上锁
printf("Input some text. Enter 'end' to finish\n");
while(!time_to_exit) //time_to_exit值由另一线程修改
{
fgets(work_area, WORK_SIZE, stdin); //从stdin读取到一行信息
pthread_mutex_unlock(&work_mutex); //解锁,两个线程抢占互斥量
while(1)
{
pthread_mutex_lock(&work_mutex); //上锁
if (work_area[0] != '\0') //检查读入的内容输出没有
{ //输出线程将信息输出后将设置work_area[0]!='\0'
pthread_mutex_unlock(&work_mutex); //如果没有输出,解锁
sleep(1);
}
else //如果已经输出,执行下一轮读入
break;
}
}
pthread_mutex_unlock(&work_mutex); //解锁
printf("\nWaiting for thread to finish...\n");
res = pthread_join(a_thread, &thread_result); //等待另一个线程结束
if (res != 0)
{
printf("Thread join failed");
exit(EXIT_FAILURE);
}
printf("Thread joined\n");
pthread_mutex_destroy(&work_mutex); //销毁互斥锁
exit(EXIT_FAILURE);
}
void *thread_function(void *arg) //子线程执行的程序
{
sleep(1);
pthread_mutex_lock(&work_mutex); //上锁,抢占资源
while(strncmp("end", work_area, 3) != 0) //判断是否为结束信息end
{
printf("You input %d characters\n", strlen(work_area) - 1); //输出输入的字符个数
printf("the characters is %s", work_area); //输出输入的字符内容
work_area[0] = '\0'; //设置最后1位为'\0',标识已经输出
pthread_mutex_unlock(&work_mutex); //解锁
sleep(1);
pthread_mutex_lock(&work_mutex); //上锁
while (work_area[0] == '\0') //判断第一位是否为'\0',如果为'\0',标识主线程还没有输入数据
{ //如果不为'\0',则表示有输入,执行下一轮输出操作
pthread_mutex_unlock(&work_mutex); //解锁,等待
sleep(1);
pthread_mutex_lock(&work_mutex); //上锁,再次返回判断
}
}
time_to_exit = 1; //置结束标识位,通知主线程操作结束
work_area[0] = '\0';
pthread_mutex_unlock(&work_mutex); //解锁
pthread_exit(0); //退出
}
undefined reference to 'pthread_create'
undefined reference to 'pthread_join'
问题原因:
pthread 库不是 Linux 系统默认的库,连接时需要使用静态库 libpthread.a,所以在使用pthread_create()创建线程,以及调用 pthread_atfork()函数建立fork处理程序时,需要链接该库。
问题解决:
在编译中要加 -lpthread参数
gcc mutex_example mutex_example.c -lpthread
mutex_example.c为你些的源文件,不要忘了加上头文件#include