一、线程的同步互斥
临界区:访问共享资源的代码段
临界资源:临界区中被读写的共享资源,即同时只能被一个进程访问的资源
线程之间,如果要进行通信,需要引入同步互斥机制,避免产生竞态,保证任何时候都只有一个线程处理临界资源
二、互斥锁
2.1 工作原理
对于要访问临界资源的线程,在访问前,都先执行申请上锁操作,若上锁成功,则进入临界区,访问临界区资源,直到退出临界区,解开互斥锁。若上锁失败,则线程进入休眠等待阶段,等待互斥锁被打开。
2.2 创建互斥锁
函数:pthread_mutex_init
功能:创建并初始化一把互斥锁
函数原型:
#include <pthread.h>
pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER; //创建方式一
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr); //创建方式二
参数:
pthread_mutex_t *mutex:存储申请以及初始化后的互斥锁
pthread_mutexattr_t *mutexattr:互斥锁属性,可以定义互斥锁是用于进程还是线程。可以用pthread_mutexattr_init函数修改互斥锁属性,一般填NULL,代表用于线程
返回值:
永远返回0;
2.3 上锁
函数:pthread_mutex_lock
功能:进行上锁,若有其他线程占用互斥锁,该函数会阻塞
函数原型:
#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);
参数:
pthread_mutex_t *mutex:指定要上的互斥锁
返回值:
成功,返回0
失败,返回非0
2.4 解锁
函数:pthread_mutex_unlock
功能:解开互斥锁
函数原型:
#include <pthread.h>
int pthread_mutex_unlock(pthread_mutex_t *mutex);
参数:
pthread_mutex_t *mutex:指定要解开的互斥锁
返回值:
成功,返回0
失败,返回非0
2.5 销毁锁
函数:pthread_mutex_dsetroy
功能:销毁互斥锁
函数原型:
#include <pthread.h>
int pthread_mutex_destroy(pthread_mutex_t *mutex);
参数:
pthread_mutex_t *mutex:指定要销毁的互斥锁
返回值:
成功,返回0
失败,返回非0
2.6 死锁
死锁出现的原因:拥有所资源的线程没有解开互斥锁,常有一下几种情况:
- 持有互斥锁的线程异常退出,没有释放锁资源
- 同一线程对一把互斥锁重复上锁
- 互斥锁交叉嵌套
示例代码(创建两个线程,一个线程负责打印,一个线程负责逆置)
#include <stdio.h>
#include <pthread.h>
#include <string.h>
//临界资源
char buf[] = "AAAA____BBBB";
//互斥锁变量 方式二
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void* callback1(void* arg)
{
while(1)
{
/******临界区************/
//上锁
pthread_mutex_lock(&mutex);
printf("%s\n", buf);
//解锁
pthread_mutex_unlock(&mutex);
/******临界区************/
}
pthread_exit(NULL);
}
void* callback2(void* arg)
{
char temp = 0;
while(1)
{
/******临界区************/
//上锁
pthread_mutex_lock(&mutex);
for(int i=0; i<strlen(buf)/2; i++)
{
temp = buf[i];
buf[i] = buf[strlen(buf)-1-i];
buf[strlen(buf)-1-i] = temp;
}
//解锁
pthread_mutex_unlock(&mutex);
/******临界区************/
}
pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
/*
//创建互斥锁:方式一
if(pthread_mutex_init(&mutex, NULL) != 0)
{
fprintf(stderr, "pthread_mutex_init failed __%d__\n", __LINE__);
return -1;
}
*/
pthread_t tid1, tid2;
//创建线程:打印
if(pthread_create(&tid1, NULL, callback1, NULL) != 0)
{
fprintf(stderr, "pthread_create failed\n");
return -1;
}
pthread_detach(tid1);
//创建线程:倒置
if(pthread_create(&tid2, NULL, callback2, NULL) != 0)
{
fprintf(stderr, "pthread_create failed\n");
return -1;
}
pthread_join(tid2, NULL);
//销毁互斥锁
pthread_mutex_destroy(&mutex);
return 0;
}