互斥:任一时刻,只有一个线程进入临界区访问临界资源且访问时具有原子性。
互斥机制的实现:互斥锁。
虽然多个线程共享同一地址空间,使得多个线程之间可以很方便的进行通信,但是当多个线程访问同一临界资源时,很可能出现访问冲突的问题。所以此时就要引入同步与互斥机制(本篇主要讲解互斥机制)
来看下面的代码:
#include<stdio.h>
#include<pthread.h>
int g_val = 0;
void* thread(void* _val)
{
int val = 0;
int count = 5000;
while(count--)
{
val = g_val;
printf("tid:%u,Mycount = %d\n",pthread_self(),val);
g_val = val+1;
}
return (void *)0;
}
int main()
{
pthread_t tid1,tid2;
pthread_create(&tid1,NULL,thread,NULL);
pthread_create(&tid2,NULL,thread,NULL);
sleep(3);
void *val;
pthread_join(tid1,&val);
pthread_join(tid2,&val);
printf("g_val = %d\n",g_val);
return 0;
}
再看看运行结果:
两个线程都对全局变量g_val进行了5000次的++操作,其值应该为10000,但是此时却为5246,这是因为创建的两个线程同时对临界资源访问时产生了干扰。为了避免这种情况,就要加入互斥锁(mutex).
互斥锁:保证共享资源数据的完整性。互斥锁主要用来保护临界资源,每个临界资源都由一个互斥锁来保护,任何时刻最多只能有一个线程访问该资源。线程必须先获得互斥锁才能访问临界资源,访问完临界资源后释放该锁。如果无法获得锁,线程会阻塞直到获得锁为止。
定义一个互斥锁:Mutex由pthread_mutex_t变量来定义。
(1)使用宏定义PTHREAD_MUTEX_INITIALIZER来初始化互斥锁:pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER
(2)int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);//attr:互斥锁的属性,一般使用默认值为NULL
加锁: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);
一个线程可以调用pthread_mutex_lock获得Mutex,如果这时另一个线程已经调用pthread_mutex_lock获得了该Mutex,则当前线程需要挂起等待(即阻塞式获得锁),直到另一个线程调用pthread_mutex_unlock释放Mutex,当前线程被唤醒,才能获得该Mutex并继续执行。
如果一个线程既想获得锁,又不想挂起等待,可以调用pthread_mutex_trylock,如果Mutex已经被另一个线程获得,这个函数会失败返回EBUSY,而不会使线程挂起等待(即非阻塞式获得锁)。
对上面的程序加入互斥锁:
#include<stdio.h>
#include<pthread.h>
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER//定义一个互斥锁
int g_val = 0;
void* thread(void* _val)
{
int val = 0;
int count = 5000;
while(count--)
{
pthread_mutex_lock(&mutex);//加锁
val = g_val;
printf("tid:%u,Mycount = %d\n",pthread_self(),val);
g_val = val+1;
pthread_mutex_unlock(&mutex);//解锁
}
return (void *)0;
}
int main()
{
pthread_t tid1,tid2;
pthread_create(&tid1,NULL,thread,NULL);
pthread_create(&tid2,NULL,thread,NULL);
sleep(3);
void *val;
pthread_join(tid1,&val);
pthread_join(tid2,&val);
pthread_mutex_destroy(&mutex);//销毁互斥锁
printf("g_val = %d\n",g_val);
return 0;
}