【Linux】—— Linux线程同步

Linux线程同步

前面我们在Linux线程基本概念 介绍了线程基本概念,在Linux线程控制中介绍了线程创建,线程终止,线程等待,线程分离等等概念,在Linux线程互斥 中介绍了互斥量这一重要的概念,那今天我们接着认识我们线程,介绍一下线程同步相关的概念

同步的概念

我们前面在线程互斥介绍了互斥这一概念,互斥简单的来说就是某个时刻只允许一个线程访问临界资源,那我们来举个栗子说明一下我们为什么在有了互斥机制的情况下有需要有同步机制。

  • 举个栗子:假设学校有一间自习室只有一个位置,那有一天你准备去学校自习室上自习,起的很早去拿了钥匙开门进去开始自习,但是在自习了一分钟之后,突然不想自习了想出去玩一会,走到门口刚刚准备把钥匙挂在门上又想得好好学习啊,于是又打开门进了自习室,刚刚坐下一分钟又想出去玩了,于是又出来之后一想还是学习吧,又打开门进去,此时门口其实已经等了一大批人准备在这个教室自习,可以你就不停的打开门进去自习一分钟又出来又打开门进去自习一分钟,重复的做这件事,如此反复导致门口所有等着自习的人均无法进行自习,这就导致了饥饿问题,于是老师在自习室门口贴了一条规定,在你进去自习出来之后如果还想接着自习就必须到教室外面排队等待自习,这样就保证了所有的同学都能够得到自习的机会。

从上面的例子我们发现,拿走钥匙不让其他人入内其实是一种互斥的机制,但是为了解决饥饿问题,后来加入了排队机制,这其实就是一种同步的机制。现在相信你对同步有了进一步的理解,我们可以认为,互斥机制是为了保证安全,同步机制为了保证合理性

  • 同步:在保证数据安全的前提下,让线程能够按某种特定的访问顺序访问临界资源,从而有效的避免饥饿问题,叫做同步
  • 竞态条件:因为时序问题,而导致程序异常,我们称之为竞态条件

条件变量

同步的机制是为了保证我们访问数据的合理性顺序,从某种角度上来说,这种合理性还要保证不同线程访问共享资源时的效率。这又该怎么理解呢?同样我们使用上面的例子接着说

  • 假设你很热爱自习,所以每次你都去的最早,所以当其他同学来的时候就要排队等待,这些等待的同学每隔几分钟就去看一次你是否离开,但是你因为热爱自习所以经常自习很久,这些等待的同学有时候会浪费一整天时间来看你是否自习结束。因此自习室后来又加入了通知的机制,当自习室没有人时就会通知其他人,这样使同学们的效率大大提高。

所以就如同上面的例子,Linux下的通知机制引入了条件变量确保了同步的合理性和高效性。当一个线程互斥地访问某个变量,它可能发现在其它线程改变状态之前,它什么也做不了。例如一个线程访问队列时,发现队列为空,它只能等待,只到其它线程将一个节点添加到队列中。这种情况就需要用到条件变量,下面我们来看看条件变量的函数,了解一下条件变量的相关接口和如何使用的

条件变量函数

  • 初始化
    条件变量初始化
  • 销毁
    销毁
  • 等待条件满足
    wait
  • 唤醒等待
    唤醒等待
    我们通过一个简单的代码来看一下应该怎么使用条件变量,下列程序的结果是:此程序r2中的signal函数每隔1秒唤醒一次r1函数,所以每秒打印一次i am a thread...
    条件变量的使用

为什么pthread_cond_wait需要互斥量

  • 条件等待是线程间同步的一种手段,如果只有一个线程,条件不满足,一直等下去都不会满足,所以必须要有一个线程通过某些操作,改变共享变量,使原先不满足的条件变得满足,并且友好的通知等待在条件变量上的线程。
  • 条件不会无缘无故的突然变得满足了,必然会牵扯到共享数据的变化。所以一定要用互斥锁来保护。没有互斥锁就无法安全的获取和修改共享数据。
    pthread_cond_wait
    按照上面的说法,我们设计出如下的代码:先上锁,发现条件不满足,解锁,然后等待在条件变量上不就行了,如下代码:
// 错误的设计
pthread_mutex_lock(&mutex);
while (condition_is_false) {
	pthread_mutex_unlock(&mutex);
	//解锁之后,等待之前,条件可能已经满足,信号已经发出,但是该信号可能被错过
	pthread_cond_wait(&cond);
	pthread_mutex_lock(&mutex);
}
pthread_mutex_unlock(&mutex);
  • 由于解锁和等待不是原子操作。调用解锁之后,pthread_ cond_ wait之前,如果已经有其他线程获取到互斥量,摒弃条件满足,发送了信号,那么pthread_ cond_ wait将错过这个信号,可能会导致线程永远阻塞在这个pthread_ cond_ wait。所以解锁和等待必须是一个原子操作。
  • int pthread_cond_wait(pthread_cond_ t *cond,pthread_mutex_ t * mutex); 进入该函数后,会去看条件量等于0不?等于,就把互斥量变成1,直到cond_ wait返回,把条件量改成1,把互斥量恢复成原样。

总结

其实线程同步这块的知识点并不多,我们只要知道为什么需要线程同步,怎么实现进程同步,还有条件变量的使用等相关概念即可

发布了167 篇原创文章 · 获赞 175 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/chenxiyuehh/article/details/97268758