การเขียนโปรแกรม D - ภาวะพร้อมกัน

การทำงานพร้อมกันทำให้โปรแกรมทำงานบนเธรดหลายชุดพร้อมกัน ตัวอย่างของโปรแกรมที่ทำงานพร้อมกันคือเว็บเซิร์ฟเวอร์ที่ตอบสนองไคลเอนต์จำนวนมากในเวลาเดียวกัน การเกิดพร้อมกันเป็นเรื่องง่ายเมื่อส่งผ่านข้อความ แต่เขียนได้ยากมากหากใช้ข้อมูลร่วมกัน

ข้อมูลที่ส่งผ่านระหว่างเธรดเรียกว่าข้อความ ข้อความอาจประกอบด้วยประเภทใดก็ได้และตัวแปรจำนวนเท่าใดก็ได้ ทุกเธรดมีรหัสซึ่งใช้สำหรับระบุผู้รับข้อความ เธรดใด ๆ ที่เริ่มเธรดอื่นเรียกว่าเจ้าของกระทู้ใหม่

การเริ่มต้นเธรดใน D

ฟังก์ชัน spawn () ใช้ตัวชี้เป็นพารามิเตอร์และเริ่มเธรดใหม่จากฟังก์ชันนั้น การดำเนินการใด ๆ ที่ดำเนินการโดยฟังก์ชันนั้นรวมถึงฟังก์ชันอื่น ๆ ที่อาจเรียกใช้จะถูกดำเนินการบนเธรดใหม่ เจ้าของและผู้ปฏิบัติงานทั้งสองเริ่มดำเนินการแยกกันราวกับว่าเป็นโปรแกรมอิสระ

ตัวอย่าง

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

ตัวระบุเธรดใน D

thisTidตัวแปรทั่วโลกที่มีอยู่ในระดับโมดูลอยู่เสมอ ID ของด้ายปัจจุบัน นอกจากนี้คุณยังสามารถรับ threadId เมื่อเรียก spawn ตัวอย่างแสดงด้านล่าง

ตัวอย่าง

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)

ข้อความผ่านใน D

ฟังก์ชัน send () ส่งข้อความและฟังก์ชัน earnOnly () รอข้อความประเภทใดประเภทหนึ่ง มีฟังก์ชั่นอื่น ๆ ที่ชื่อ prioritySend (), รับ () และรับเวลาเอาท์ () ซึ่งจะอธิบายในภายหลัง

เจ้าของในโปรแกรมต่อไปนี้ส่งข้อความประเภท 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

ข้อความผ่านด้วยการรอใน D

ตัวอย่างง่ายๆกับข้อความที่ส่งด้วยการรอแสดงอยู่ด้านล่าง

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