线程需要互斥的原因:
由于多个线程同时在进程的地址空间内部运行,所以进程的大部分资源相对于线程而言都是共享的,所以当多个线程同时对于某个临界资源进行操作时,就会出现问题,所以,线程之间对于临界资源的访问需要互斥的进行访问,以便造成不确定的结果。
范例:
#include<stdio.h>
#include<pthread.h>
int _val = 0;
void* thread_run()
{
int i=0;
while(i<5000)
{
_val++;
i++;
printf("%d\n",_val);
}
printf("\n");
return NULL;
}
int main()
{
pthread_t tid = 0; //save the new thread of id;
int pth_cre = pthread_create(&tid,NULL,thread_run,NULL);
if(pth_cre != 0)
{
perror("pthread_create");
return -1;
}
int i =0;
while(i<5000)
{
int tmp = _val;
tmp = tmp + 1;
_val = tmp;
++i;
printf("%d\n",_val);
}
printf("\n");
return 0;
}
此段代码是两个线程对于同一个全局变量进行累加操作,可是运行多次,产生的结果不一定是10000;
结果:
为了解决这种问题,对于临界资源的访问,需要加上互斥锁,才能保证不同线程对于临界资源的互斥访问,使得程序向着正确的方向去推进;
代码:
#include<stdio.h>
#include<pthread.h>
int _val = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //定义mutex互斥锁
void* thread_run()
{
int i=0;
while(i<5000)
{
pthread_mutex_lock(&mutex); //加锁
_val++;
i++;
printf("%d\n",_val);
pthread_mutex_unlock(&mutex); //解锁
}
printf("\n");
return NULL;
}
int main()
{
pthread_t tid = 0; //save the new thread of id;
int pth_cre = pthread_create(&tid,NULL,thread_run,NULL);
if(pth_cre != 0)
{
perror("pthread_create");
return -1;
}
int i =0;
while(i<5000)
{
pthread_mutex_lock(&mutex); //加锁
int tmp = _val;
tmp = tmp + 1;
_val = tmp;
++i;
printf("%d\n",_val);
pthread_mutex_unlock(&mutex); //解锁
}
pthread_join(tid,NULL);
printf("\n");
pthread_mutex_destroy(&mutex);
return 0;
}
对于临界资源的访问要进行互斥访问,但是由于互斥访问中某些线程的优先级的问题会导致死锁问题的发生;
死锁
产生死锁的原因:
(1)竞争不可抢占性资源引起死锁;
(2)竞争可消耗性资源引起死锁;
(3)线程推进顺序不当引起死锁;
死锁的概念:
如果一组进程中的每一个进程都在等待仅由改组进程中的其他进程才能引发的事件,那么,改组进程就是死锁的。
注:对于一个进程中的多个线程也是如此:当某个进程中的所有线程都在等待由这个进程中的线程才能引发的事件,那么,这个进程中的所有线程都处于死锁状态;
产生死锁的必要条件:
(1)互斥条件:进程对于所分配到的资源进行排他性使用,在某一段时间段内,某资源只能被一个进程使用。则:此时如果有其他 进程请求该资源,只能等待,直到该进程将此资源释放才可以使用;
(2)请求和保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,但是该资源已经被其他进程占有,,此时请求进程被阻塞,但是对于自己保持的资源请求不放。
(3)不可抢占条件:进程已经获得的资源在未使用完之前不能被抢占,只能在进程使用完之后自己释放;
(4)循环等待条件:在发生死锁时:必然存在一个进程----资源的循环链。
避免死锁的算法:
银行家算法:每一个进程在进入系统时,它必须申明在运行过程中可能需要某种资源数目的最大数目,其数目不应该超过系统所拥有的资源总量。当进程请求一组资源时:系统必须首先确定是否有足够的资源分配给该进程;若有:再进一步计算在将这些资源分配给该进程后,是否会使系统处于不安全状态。如果不会,才将资源分配给该进程。
注:系统安全状态:
所谓安全状态,是指系统能够按照某种进程推进顺序,为每个进程分配其所需要带的资源,直到满足每个进程对于资源的最大需求,使得每个进程都可以顺利完成。系统安全状态下所对应的进程的推进顺序为安全序列。