线程互斥和同步-- 互斥锁

时间:2023-02-05 21:38:48
一. 线程分离 我们一般创建的线程是可结合的,这个时候如果我们调用pthread_jion()去等待的话,这种等待的方式是阻塞式等待,如果主线程一直等待,主线程就无法做其他的事情了,所以应该使用线程分离,让子线程由操作系统回收,主线程就不管了。 不管线程是否分离,它始终是在进程的内部执行的。 使用的函数接口是pthread_detach(pthread_t pid) 如果分离自己参数为pthread_self(),如果是主线程分离子线程,参数为pthread_id 二. 线程互斥 因为我们的多个线程是共享一个资源的,这个资源就是临界资源,多个线程对资源的访问就需要使用线程的同步和互斥 互斥,对资源的访问时串行的,原子的。即是,每次只能有一个线程访问临界 资源 三.线程同步 如果我们的某一个线程的优先级特别高,那么它可能会一直占据这这临界资源,这个时候,其他的线程就无法使用这个临界资源,虽然我们实现了线程的互斥,但是只有一个线程 使用它,这也是不符合我们的实际需求的,所以这个时候需要使用线程的同步。 线程同步的意思就是说,每次使用完一个临界资源之后,都需要排队,打个形象的比喻就是,如果我们一个人进入一个单独自习室自习之后,出来的时候,必须排在其他的排在门口的人后面,不能直接出来又进去,这样的话,他就是一直占据着临界资源了。 四. 互斥锁 设置一个互斥锁,这个时候一次,创建一个全局的互斥锁。 在线程函数里面,每次一个线程 访问的临界资源的时候,首先要做的是就是获取这个锁,只有拿到锁之后才能对临界资源进行操作,然后每次在退出临界资源之前,要解锁,这样其他的线程进入的时候才不会永远拿不到锁。 整个函数结束前,要销毁锁。
对于互斥锁的一个深层次的理解 1. 互斥锁本身就是一个临界资源,所以对互斥锁的操作本身就是原子的。 2. 每次在线程 函数的内部,每次需要申请锁资源,如果申请失败,当前的线程就会被挂起,挂起就是该线程的PCB在等待队列里面。
死锁产生的情景 1. 多线程可能有多把锁,这个时候,如果其中的某些线程 都想要访问彼此的锁,这个时候可能 都拿不到,然后就产生了死锁。 2. 一个进程一把锁,可能由于代码错误,当它申请锁之后,已经 拿到了这把锁,然后他又去申请同样 的,这个时候就出现了死锁。
下面看代码的实现。
#include<stdio.h>
#include<pthread.h>
int count = 0;

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; //创建一把锁,使用宏进行初始化

void* pccount(void* arg)
{
int i = 0;
int temp = 0;
while(i<50000000)
{
pthread_mutex_lock(&lock); //加锁,如果锁资源是空,就拿到锁,如果锁资源不是空,就挂起等待
//temp=count;
count=count+1;
//printf("%d",temp);
i++;
pthread_mutex_unlock(&lock); //操作完临界资源之后,要解锁,这样其他的线程才能够获取锁资源
}
//printf("%d\n",count);
pthread_exit((void*)123);
}

int main()
{
pthread_t pid1;
pthread_t pid2;
int i = pthread_create(&pid1,NULL,pccount,NULL);

int m = pthread_create(&pid2,NULL,pccount,NULL);
void* join1;
void* join2;
pthread_join(pid1,&join1);

pthread_join(pid2,&join2); //这里必须要有线程等待,不然没有打印结果
pthread_mutex_destroy(&lock); //销毁锁资源
printf("%d\n",count);
return 0;

}