7

线程通信背后的共同理论是什么?我对它应该如何工作有一些原始的想法,但有些东西对我来说并不好。有没有办法通过中断来做到这一点?

4

5 回答 5

11

实际上,它与任何并发问题相同:您有多个控制线程,并且不确定何时执行哪些线程上的哪些语句。这意味着程序中有大量的 POTENTIAL 执行路径,并且您的程序必须在所有这些路径下都是正确的。

通常,可能出现问题的地方是线程之间共享状态(过去称为“轻量级进程”)。当有共享内存区域时,就会发生这种情况,

为了确保正确性,您需要做的是确保以不会导致错误的方式更新这些数据区域。为此,您需要识别程序的“关键部分”,其中必须保证顺序操作。这些可以少到一条指令或一行代码;如果语言和架构确保这些是原子的,即不能被中断,那么你就是黄金。

否则,您将识别该部分,并在其上放置某种保护措施。经典的方法是使用信号量,它是一种原子语句,一次只允许一个控制线程过去。这些是由 Edsgar Dijkstra 发明的,因此有来自荷兰语、PV的名称。当你来到P时,只有一个线程可以继续;所有其他线程都排队等待,直到执行线程到达关联的V操作。

因为这些原语有点原始,而且荷兰语的名称不是很直观,所以已经开发了一些更大规模的方法。

Per Brinch-Hansen 发明了monitor,它基本上只是一个数据结构,具有保证原子的操作;它们可以用信号量来实现。监视器几乎是 Javasynchronized语句的基础。它们使对象或代码块具有特定的行为——也就是说,一次只能有一个线程“进入”它们——语法更简单。

还有其他可能的模式。Haskell 和 Erlang 通过函数式语言解决了这个问题,它们一旦创建就不允许修改变量;这意味着他们自然不需要担心同步问题。一些新的语言,比如 Clojure,有一个叫做“事务性内存”的结构,这基本上意味着当有一个赋值时,你可以保证这个赋值是原子的和可逆的。

简而言之就是这样。要真正了解它,查看操作系统文本的最佳位置,例如Andy Tannenbaum 的文本

于 2009-02-17T02:08:36.340 回答
5

线程通信最常见的两种机制是共享状态和消息传递

于 2009-02-17T02:23:43.963 回答
3

线程最常见的通信方式是通过一些共享数据结构,通常是队列。一些线程将信息放入队列,而另一些则将其取出。队列必须受到操作系统设施的保护,例如互斥锁和信号量。中断与它无关。

于 2009-02-17T02:11:38.797 回答
1

要在线程之间进行通信,您需要使用操作系统和/或运行时提供的任何机制。中断将异常低级别,尽管如果您的线程使用套接字或命名管道进行通信,它们可能会被隐式使用。

一种常见的模式是使用共享内存块来实现共享状态,依靠操作系统提供的同步原语(例如互斥锁)来避免您在从块中读取时忙于等待。请记住,如果您有线程,那么您必须已经有某种调度程序(无论它是来自操作系统的本机还是在您的语言运行时中模拟)。所以这个调度器可以提供同步对象和“睡眠”功能,而不必依赖硬件支持。

套接字、管道和共享内存也在进程之间工作。有时,运行时会为您提供一种更轻量级的方式来为同一进程中的线程进行同步。共享内存在单个进程中更便宜。有时你的运行时也会给你一个原子的消息传递机制。

于 2009-02-17T02:12:34.957 回答
1

如果您真的对线程通信理论感兴趣,您可能需要研究像pi Calculus这样的形式。

于 2009-02-17T02:22:30.003 回答