线程为什么要同步
1 共享资源,多个线程都可对共享资源操作
2 线程操作共享资源的先后顺序不确定
3 处理器对存储的操作一般不是操作
临界区
保证在某一时刻只有一个线程能访问数据的简便方法,在任意时刻只允许一个线程对共享资源进行访问,如果又多个线程试图同时访问临界区,那么在又一个线程进入后,其他所有试图访问因此临界区的线程将被挂起,并一直持续到进入临界区的线程离开,临界区在被释放后,某其他线程可以继续抢占,并以此达到用原子方式操作共享资源的目的
临界区的选定
临界区的选定因此可能小,如果选定太大会影响程序的并行处理性能
互斥锁相关函数
初始化互斥锁:
pthread_mutex_init(
pthread_mutex_t *mutex,
const pthread_mutexattr_t *attr
);
销毁互斥锁:
pthread_mutex_destroy(pthread_mutex_t *mutex);
加锁:
pthread_mutex_lock(pthread_mutex_t *mutex);
mutex:
没有被上锁,当前线程会将这把锁锁上
被锁上了:当前线程阻塞(锁被打开之后,线程解除阻塞)
尝试加锁,失败返回,不阻塞
pthread_mutex_trylock(pthread_mutex_t *mutex);
没有加锁的话:当前进程会给这把锁加锁
如果锁上了:不会阻塞,返回
if(pthread_mutex_trylock(&mutex)==0)
// 尝试加锁,并且成功了
// 访问共享资源
{
}
else
// 错误处理
// 或者 等一会,再次尝试加锁
{
}
解锁:
pthread_mutex_unlock(pthread_mutex *mutex);
如果我们想使用互斥锁同步线程:所有的线程都需要加锁
初始化时相当于有了一把锁(1)
pthread_mutex_lock(&mutex) mutex=1;
操作共享资源的代码之前加锁
pthread_mutex_lock(&mutex); 使用这个函数的时候会判断mutex是否为1,也就是有锁,有锁的话加锁,mutex变为0,如果mutex为0,也就是这把被用了,就会阻塞
临界区。。
pthread_mutex_unlock(&mutex) --解锁后mutex会变成1
代码(没加锁):
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#define LOOP 5000
int number=0;
void *th_fun(void *sig)
{
int var;;
for(int i=0;i<LOOP;i++)
{
var=number;
number=var+1;
printf("%x---%d\n",(unsigned int)pthread_self(),number);
usleep(10);
}
return NULL;
}
int main()
{
pthread_t ta,tb;
pthread_create(&ta,NULL,th_fun,NULL);
pthread_create(&tb,NULL,th_fun,NULL);
pthread_join(ta,NULL);
pthread_join(tb,NULL);
return 0;
}
会出现数据覆盖的问题
代码(加锁):
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#define LOOP 5000
int number=0;
pthread_mutex_t mutex;
void *th_fun(void *sig)
{
int var;;
for(int i=0;i<LOOP;i++)
{
pthread_mutex_lock(&mutex);
var=number;
number=var+1;
printf("%x---%d\n",(unsigned int)pthread_self(),number);
pthread_mutex_unlock(&mutex);
usleep(10);
}
return NULL;
}
int main()
{
pthread_t ta,tb;
//初始化互斥锁
pthread_mutex_init(&mutex,NULL);
pthread_create(&ta,NULL,th_fun,NULL);
pthread_create(&tb,NULL,th_fun,NULL);
pthread_join(ta,NULL);
pthread_join(tb,NULL);
pthread_mutex_destroy(&mutex);
return 0;
}
不会出现问题