
课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
我们在前几期的文章中给大家简单介绍了进程与线程等软件编程开发基础知识,而本文我们就继续来学习一下,并发编程开发通信的问题都有哪些。
多个进程线程需要协调,彼此之间就需要通信。那进程间通信一般会有什么问题?
竞争条件和临界区
竞争条件-两个或多个进程共享读写数据,而后的结果取决于进程运行的精确时序,称为竞争条件(racecondition)。
怎么避免竞争条件?
凡涉及到共享内存、共享文件及共享任何资源都可能引起这种错误,要避免这种错误,关键是要找出某种途径来阻止多个进程同时读写共享的数据。换言之,我们需要互斥,即用某种手段确保当一个进程使用一个共享变量或文件时,其他进程不能做同样的操作。
我们把共享内存进行访问的程序片段称为临界区或临界区域。如果我们能使两个进程不可能同时处于临界区中,就能避免竞争条件。
忙等待互斥
书中提到了忙等待互斥的几个方法:Peterson解法和TSL和XCHG,这些解法本质上:当一个进程进入临界区,先检查是否允许进入,若不允许,则该进程将原地等待,直到允许位置。
缺点:浪费CPU,还可能引起预想不到的结果。如果是等待时间非常短,则可以用。
睡眠与唤醒
进程无法进入临界区时将阻塞,而不是忙等待。
简单的就是sleep和wakeup。sleep是一个将引起系统进程阻塞的调用,即被挂起,直到另外一个进程将其唤醒。
应用就是生产者-消费者。
信号量
信号量(semaphore)是E.W.Dijkstra在1965年提出的一种方法,它使用一个整型变量来累计唤醒次数,供以后使用。
用信号量也可以解决生产者-消费者问题。
互斥量
互斥量是信号量简化的一个版本,不需要计数。互斥量是一个处于两种状态之一的变量:加锁和解锁。
互斥量使用两个过程:
当一个线程需要访问临界区,它调用mutex_lock。如果互斥量当前是解锁的(即临界区可用),此调用成功,调用线程可自由进入临界区。
另一方面,如果该互斥量已经加锁,调用线程阻塞,直到在临界区的线程完成并调用mutex_unlock。
如果多个线程阻塞在互斥量上,将随机选择一个线程并允许它获得锁。
管程和条件变量
BrinchHansen(1973)和Hoare(1974)提出了一种高级同步原语,称为管程(monitor)。
一个管程是有一个过程、变量及数据结构等组成的一个集合,他们组成一个特殊的包或者软件包。
管程是一种语言的概念。管程有一个很重要的特性,即任一时刻管程中只能有一个活跃进程,这一特性使管程能有效地完成互
斥。管程是编程语言的组成部分,编译器知道它们的特殊性。
进入管程时的互斥由编译器负责,但通常的做法是用一个互斥量或二元信号量。因为是由编译器而非程
序员来安排互斥,所以出错的可能性要小得多。在任一时刻,写管程的人无须关心编译器是如何实现互斥
的。他只需知道将所有的临界区转换成管程过程即可,决不会有两个进程同时执行临界区中的代码
当然解决生成者-消费者,缓存区满的问题,引入了条件变量(conditionvariables)以及相关2个操作:wait和signal。
在管程运行过程中发现生成者满时,它可以在条件变量上执行wait操作。该操作会导致调用进程自身阻塞,并且还将另一个以前等在管程之外的进程调入管程。
另外一个进程,比如消费者,还可以唤醒正在睡眠的伙伴进程。这可以通过对其伙伴正在等待的一个条件变量执行signal完成。
消息传递
进程间通信的方法使用两条原语send和receive。
Go语言中通过channel在goroutine之间安全的传递消息。
【免责声明】:本内容转载于网络,转载目的在于传递信息。文章内容为作者个人意见,本平台对文中陈述、观点保持中立,不对所包含内容的准确性、可靠性与完整性提供形式地保证。请读者仅作参考。更多内容请加danei456学习了解。欢迎关注“达内在线”参与分销,赚更多好礼。