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