1.线程之间可以是共享内存的,但是,系统中的部分资源有时候是需要互斥的,即当一个线程在访问这个资源时,其他的线程不能进行访问,否则会出现产生不安全的数据。比如,在卖票系统中,如果多个线程同时去卖票,会产生错误的结果:线程1在卖第1张票,但是还未改变票数,此时,线程2抢占到系统资源,进行卖票,那么线程2卖的也是第1张票,与我们期待的结果相矛盾。
2.像类似于卖票系统的中票数这样需要互斥,同一时刻只能一个系统访问的资源,我们可通过互斥锁来实现。利用互斥锁我们可以将资源或一段代码锁起来,被锁住的资源或代码只能由上锁的系统使用,其他的系统、线程无法访问。只有当资源被解锁以后,其他的系统、线程才能访问。通过互斥锁可以提高数据访问的安全性。
3.利用互斥锁实现卖票系统的代码如下:
/*通过互斥锁实现共享资源的安全访问*/
/*利用子进程模拟卖票的系统,共享资源为数量一定的票数*/
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
int ticket = 1000; //总共的票数
//创建互斥锁变量
pthread_mutex_t mutex;
//线程需要执行的代码逻辑
void * sell(void * arg)
{
while(1)
{
//加锁
pthread_mutex_lock(&mutex);
if(ticket > 0)
{
usleep(8000);
printf("线程%ld 正在出售第 %d 张票\n",pthread_self(),ticket);
ticket --;
}
else{
//解锁
pthread_mutex_unlock(&mutex);
break;
}
//解锁
pthread_mutex_unlock(&mutex);
}
return NULL;
}
int main()
{
//初始化互斥锁变量
pthread_mutex_init(&mutex,NULL);
//创建子线程
pthread_t tid1,tid2,tid3;
pthread_create(&tid1,NULL,sell,NULL);
pthread_create(&tid2,NULL,sell,NULL);
pthread_create(&tid3,NULL,sell,NULL);
//连接线程,进行资源回收,阻塞。或者可利用设置线程分离,回收资源
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
pthread_join(tid3,NULL);
//释放互斥锁资源
pthread_mutex_destroy(&mutex);
//退出主线程
pthread_exit(NULL); //执行了线程退出函数,其后面的代码不会再执行,同时,主线程的结束,不会影响子线程
return 0;
}
4.运行结果:
5.总结:互斥锁的创建步骤为创建互斥锁变量、初始化互斥锁变量、给资源上锁、 给资源解锁,最后在整个系统结束以后需要释放互斥锁资源。利用互斥锁可提高数据访问的安全性,但是,一定程度上减少了系统的并发,因为,在遇到被上锁的资源时,此刻只能由当前上锁的线程访问,而其他的线程只能等待资源被解锁以后,才能进行访问。