在計算中,通道(channel)是通過消息傳遞進行進程間通信同步的編程模型。作為一個,消息可以經由通道發送,另一個進程或線程能夠接收它已經引用的經由通道發送的消息。通道的不同實現,可以沒有緩衝區也可以有緩衝區,消息傳遞相應的可以是同步的也可以是異步的。

通道是並發的進程演算方式的基礎,並起源於通信順序進程(CSP),它是並發的形式模型,在CSP的無緩衝區通道中,發送者不能傳送消息,直到接收者準備好接受它,稱為同步消息傳遞,這種行為也被形象的稱為「約會」(rendezvous)。通道已經用在了很多CSP派生語言中,比如occamLimbo編程語言(經歷了NewsqueakAlef英語Alef (programming language)語言)。通道還用於貝爾實驗室Plan 9的libthread,以及用於Stackless PythonGo編程語言。

通道實現

編輯

通道是固有同步I/O:一個進程等待接收來自一個通道的對象,它將會阻塞直到這個對象被發送了。

libthread通道

編輯

多線程庫libthread[1],它最初是為操作系統Plan 9建立的,提供了基於固定大小的通道的線程間通信。下面用libthread通道API的例子來說明典型支持的操作。

  • 固定或可變大小的通道建立,返回引用或句柄(handle):
    Channel* chancreate(int elemsize, int bufsize)
    
  • 發送到一個通道:
    int chansend(Channel *c, void *v)
    
  • 接收自一個通道:
    int chanrecv(Channel *c, void *v)
    

OCaml事件

編輯

OCaml事件模塊提供有類型的通道用於同步。在調用這個模塊的發送和接收函數的時候,它們建立可以被同步的相應發送和接收事件。

例子

編輯

Go允許通道緩衝內容,而且還有通過使用select阻塞而得到的非阻塞接收[2]。下面是演示通道和goroutine協程用法Go代碼片段:

c := make(chan int)  // 分配一个通道
// 启动一个goroutine在其中做排序;当它完成时,在通道上发信号
go func() {
    list.Sort()
    c <- 1  // 发送一个信号,值无关紧要
}()
doSomethingForAWhile()
<-c   // 等待排序结束;丢弃发来的值

Rust提供了在線程之間的異步通道。通道允許在兩個端點SenderReceiver之間的單向的信息流動[3]

use std::sync::mpsc;
use std::thread;

fn main() {
    let (tx, rx) = mpsc::channel();

    thread::spawn(move || {
        tx.send(123).unwrap();
    });

    let result = rx.recv();
    println!("{:?}", result);
}

應用

編輯

除了用於進程間通信的基本用途之外,通道可以被用作實現能現實化為串流的各種其他並發編程構造的原語(primitive)。例如,可以使用通道了構造Future與promise,這裡的future是一個一元素通道,而promise是發送至這個通道的一個進程,它履行future[4]。類似的,迭代器可以直接用通道構造[5]

引用

編輯
  1. ^ thread(3) - Plan 9 from User Space. [2024-01-03]. (原始內容存檔於2023-09-08). 
  2. ^ 存档副本. [2020-05-04]. (原始內容存檔於2015-01-06). 
  3. ^ Channels - Rust By Example. doc.rust-lang.org. [28 November 2020]. (原始內容存檔於2024-03-24). 
  4. ^ "Futures頁面存檔備份,存於網際網路檔案館)", Go Language Patterns頁面存檔備份,存於網際網路檔案館
  5. ^ "Iterators頁面存檔備份,存於網際網路檔案館)", Go Language Patterns頁面存檔備份,存於網際網路檔案館

參見

編輯

外部連結

編輯