一、进程的互斥与同步
见本人另外一篇博客链接: 进程互斥与同步讲解.
二、Linux多线程编程—互斥量的讲解
在多线程的编程当中,如果需要访问共同的资源比如同类型的变量等。这同样也是需要我们对变量进行保护。使用pthread的互斥接口来实现互斥变量的访问,[互斥量]mutex本质来说就是一把锁,拿到锁的人才能打开门,才能进入到我们的临界资源中去访问临界资源。没有锁的人就得在外面处于堵塞状态,只到里面的人出来,外面的人才能开始争资源,谁先拿到锁,谁就能先进去访问临界资源。
在操作系统中,只有将线程做成相同数据机制访问,才能实现数据的互斥访问。操作系统并不会为我们做数据的访问的串行化,如果没有统一的规则,在访问规则的时候就会产生混乱。
在线程当中外面用pthread_mutex_t来定义锁的类型,如果是静态分配的数据量,需要用pthread_mutex_init来初始化锁,如果是动态分配互斥量,在释放内存的时侯需要调用pthread_mutex_destroy进行互斥量的销毁。
三、Linux多线程编程函数API
如何创建线程这里就不详细讲解了见链接: 线程讲解.
1.pthread_mutex_init(),初始化锁
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr)
2.pthread_mutex_destroy(),销毁一个锁
int pthread_mutex_destroy(pthread_mutex_t* mutex)
3.pthread_mutex_lock(),加锁
int pthread_mutex_lock(pthread_mutex_t* mutex)
4.pthread_mutex_unlock(),解锁
int pthread_mutex_unlock(pthread_mutex_t* mutex)
6.下面是函数的具体使用:
#include<stdio.h>
#include<string.h>
#include <pthread.h>
int data = 0; //共享数据
pthread_mutex_t mutex; //互斥量
void *fun1(void *arg)
{
printf("xianchen1:the xiancheng num is %ld\n",(unsigned long)pthread_self());//序列号
printf("xianchen1:the parm is %d\n",*((int *)arg)); //parm的值
pthread_mutex_lock(&mutex); //加锁
while(1)
{
sleep(1);
printf("xianchen:the data is %d \n",++data);
if(data==4)
{
printf("fun1 quit!************\n"); //如果等于四就退出
pthread_mutex_unlock(&mutex); //退出后解锁
pthread_exit(NULL);
}
}
}
void *fun2(void *arg)
{
printf("xianchen2:the xiancheng2 num is %ld \n",(unsigned long)pthread_self());
printf("xianchen2:the parm is %d\n",*((int *)arg));
while(1)
{
pthread_mutex_lock(&mutex);//加锁
printf("xianchen2:the data is %d\n",data++);
pthread_mutex_unlock(&mutex);//解锁
sleep(1);
}
pthread_exit(NULL);
}
int main()
{
pthread_t t1;
pthread_t t2;
int gram = 100;
//int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
int ret;
int ret2;
pthread_mutex_init(&mutex,NULL);
ret = pthread_create(&t1,NULL,fun1,(void *)&gram);
ret2 = pthread_create(&t2,NULL,fun2,(void *)&gram);
char *ptrs = NULL;
char *ptrs2 = NULL;
if (ret==0)
{
printf("main: printf xaincheng sucess!\n");
}
while(1)
{
printf("main:%d\n",data);
sleep(1);
}
pthread_join(t1,(void **)&ptrs);
pthread_join(t2,(void **)&ptrs2);
pthread_mutex_destroy(&mutex);
return 0;
}
7.测试结果
我们编程的目的达到了,就是要让线程二中的data的值加到4然后退出,让主线程和线程一去争夺资源。达到目的,实现了加锁和解锁。
四、死锁以及如何避免死锁
4.1死锁的原因
死锁是在多个线程的情况下,系统资源能够提供的资源个数比请求该资源的进程数要少,当系统中的的多个进程因申请资源得不到满足而等待时,线程都没有能力进行下一步执行,就会出现冲突造成死锁。
4.2解决死锁策略
1.采用静态资源分配方法预防死锁,即在应用程序即将进入到系统时进行,通过预先分批资源,每一个用户向系统提起资源求情,若系统能满足该请求则同意调入主存。
2.采用动态资源分配,有效避免的方法。通过动态资源分配能合理利用资源,但是会发生死锁,所以就需要一些检测算法进行检测避免产生死锁。
3.忽略死锁,在UNIX操作系统中,若发生死锁直接重启系统。避免了检测算法占用资源。