D語言併發

併發性是使程序在同一時間運行一個以上的線程。併發程序的一個例子是在Web服務器響應多個客戶端在同一時間。併發是容易與消息傳遞卻很難,如果它們是基於數據共享的寫入。

傳遞線程之間的數據被稱爲消息。消息可以由任何類型和任意數量的變量。每個線程都有一個ID,它是用於指定郵件的收件人。即啓動另一個線程的任何線程被稱爲新線程的所有者。即啓動另一個線程的任何線程被稱爲新線程的所有者。

啓動線程

spawn() 接受一個函數指針作爲參數,並從該函數啓動一個新線程。正在開展的功能,包括它可能調用其他函數的任何操作,將在新的線程中執行。owner和worker開始獨立執行的,好像他們是獨立的程序:

import std.stdio; import std.stdio; import std.concurrency; import core.thread; void worker(int a) { foreach (i; 0 .. 4) { Thread.sleep(1); writeln("Worker Thread ",a + i); } } void main() { foreach (i; 1 .. 4) { Thread.sleep(2); writeln("Main Thread ",i); spawn(&worker, i * 5); } writeln("main is done."); }

當上面的代碼被編譯並執行,它在讀取上一節中創建的文件,併產生以下結果:

Main Thread 1
Worker Thread 5
Main Thread 2
Worker Thread 6
Worker Thread 10
Main Thread 3
main is done.
Worker Thread 7
Worker Thread 11
Worker Thread 15
Worker Thread 8
Worker Thread 12
Worker Thread 16
Worker Thread 13
Worker Thread 17
Worker Thread 18

線程標識符

thisTid變量是全局可用在模塊級始終是當前線程的id。也可以收到重生時被調用threadid。一個例子如下所示。

import std.stdio; import std.concurrency; void printTid(string tag) { writefln("%s: %s, address: %s", tag, thisTid, &thisTid); } void worker() { printTid("Worker"); } void main() { Tid myWorker = spawn(&worker); printTid("Owner "); writeln(myWorker); }

當上面的代碼被編譯並執行,它在讀取上一節中創建的文件,併產生以下結果:

Owner : Tid(std.concurrency.MessageBox), address: 10C71A59C
Worker: Tid(std.concurrency.MessageBox), address: 10C71A59C
Tid(std.concurrency.MessageBox)

消息傳遞

send() 發送的消息和receiveOnly()等待一個特定類型的消息。還有prioritySend(),receive()和receiveTimeout(),這將在後面進行說明。在下面的程序的所有者將其工作者int類型的消息,並等待來自double類型的工人消息。線程繼續發送郵件來回,直到車主發出了一個負的int。一個例子如下所示。

import std.stdio; import std.concurrency; import core.thread; import std.conv; void workerFunc(Tid tid) { int value = 0; while (value >= 0) { value = receiveOnly!int(); auto result = to!double(value) * 5; tid.send(result); } } void main() { Tid worker = spawn(&workerFunc,thisTid); foreach (value; 5 .. 10) { worker.send(value); auto result = receiveOnly!double(); writefln("sent: %s, received: %s", value, result); } worker.send(-1); }

當上面的代碼被編譯並執行,它在讀取上一節中創建的文件,併產生以下結果:

sent: 5, received: 25
sent: 6, received: 30
sent: 7, received: 35
sent: 8, received: 40
sent: 9, received: 45

消息等待傳遞

一個簡單的例子與傳遞與等待消息如下所示。

import std.stdio; import std.concurrency; import core.thread; import std.conv; void workerFunc(Tid tid) { Thread.sleep(dur!("msecs")( 500 ),); tid.send("hello"); } void main() { spawn(&workerFunc,thisTid); writeln("Waiting for a message"); bool received = false; while (!received) { received = receiveTimeout(dur!("msecs")( 100 ), (string message){ writeln("received: ", message); }); if (!received) { writeln("... no message yet"); } } }

當上面的代碼被編譯並執行,它在讀取上一節中創建的文件,併產生以下結果:

Waiting for a message
... no message yet
... no message yet
... no message yet
... no message yet
received: hello