D Programlama - Eşzamanlılık
Eşzamanlılık, bir programın aynı anda birden fazla iş parçacığı üzerinde çalışmasını sağlamaktır. Eşzamanlı bir programa örnek, aynı anda birçok istemciye yanıt veren bir web sunucusudur. Eşzamanlılık, mesaj iletimi ile kolaydır, ancak veri paylaşımına dayalıysa yazmak çok zordur.
İş parçacıkları arasında aktarılan verilere mesaj denir. Mesajlar, herhangi bir türde ve herhangi bir sayıda değişkenden oluşabilir. Her iş parçacığının, mesajların alıcılarını belirtmek için kullanılan bir kimliği vardır. Başka bir iş parçacığını başlatan herhangi bir iş parçacığı, yeni iş parçacığının sahibi olarak adlandırılır.
D'de Konu Başlatma
Spawn () işlevi parametre olarak bir gösterici alır ve bu işlevden yeni bir evre başlatır. Bu işlev tarafından gerçekleştirilen tüm işlemler, çağırabileceği diğer işlevler de dahil olmak üzere, yeni iş parçacığında yürütülecektir. Sahip ve çalışan, sanki bağımsız programlarmış gibi ayrı ayrı çalışmaya başlarlar.
Misal
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.");
}
Yukarıdaki kod derlendiğinde ve çalıştırıldığında, önceki bölümde oluşturulan dosyayı okur ve aşağıdaki sonucu verir -
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'deki Diş Tanımlayıcıları
Genel olarak modül düzeyinde mevcut olan thisTid değişkeni her zaman geçerli iş parçacığının kimliğidir. Ayrıca spawn çağrıldığında threadId'i alabilirsiniz. Aşağıda bir örnek gösterilmiştir.
Misal
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);
}
Yukarıdaki kod derlendiğinde ve çalıştırıldığında, önceki bölümde oluşturulan dosyayı okur ve aşağıdaki sonucu verir -
Owner : Tid(std.concurrency.MessageBox), address: 10C71A59C
Worker: Tid(std.concurrency.MessageBox), address: 10C71A59C
Tid(std.concurrency.MessageBox)
D'de Geçen Mesaj
Send () işlevi mesajlar gönderir ve ReceOnly () işlevi belirli tipte bir mesajı bekler. PrioritySend (), take () ve ReceTimeout () adında başka fonksiyonlar da vardır ve bunlar daha sonra açıklanacaktır.
Aşağıdaki programın sahibi, çalışanına int türünde bir ileti gönderir ve double türünde bir worker (işçi) öğesinden bir ileti bekler. İş parçacığı, sahibi negatif bir int gönderene kadar ileri geri ileti göndermeye devam eder. Aşağıda bir örnek gösterilmiştir.
Misal
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);
}
Yukarıdaki kod derlendiğinde ve çalıştırıldığında, önceki bölümde oluşturulan dosyayı okur ve aşağıdaki sonucu verir -
sent: 5, received: 25
sent: 6, received: 30
sent: 7, received: 35
sent: 8, received: 40
sent: 9, received: 45
D'de Bekleyerek Geçen Mesaj
Bekleyerek geçen mesajın basit bir örneği aşağıda gösterilmiştir.
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");
}
}
}
Yukarıdaki kod derlendiğinde ve çalıştırıldığında, önceki bölümde oluşturulan dosyayı okur ve aşağıdaki sonucu verir -
Waiting for a message
... no message yet
... no message yet
... no message yet
... no message yet
received: hello