Sequenzielle Konsistenz angewandt

Inhaltsverzeichnis[Anzeigen]

In dem Artikel sequenzielle Konsistenz habe ich bereits das Defaul-Speichermodell vorgestellt. Dieses Modell, in dem die Aktionen aller Threads einer globalen Reihenfolge oder auch eines globalen Zeittaks folgen, besitzt einen großen Vorteil und einen großen Nachteil.

 

Aufwändige Synchronisation

Der große Vorteil ist es, dass sich die sequenzielle Konsistenz mit unserer Intuition des Verhaltens mehrerer Threads deckt, der große Nachteil ist, dass die Synchronisation aller Threads aufwändig vom System sicherzustellen ist.

Das kleine Programm synchronisiert seinen Producer-Thread mit seinem Consumer-Thread mit Hilfe der sequentiellen Konsistenz.

 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <atomic>
#include <iostream>
#include <string>
#include <thread>

std::string work;
std::atomic<bool> ready(false);

void consumer(){
  while(!ready.load()){}
  std::cout<< work << std::endl;   
}

void producer(){
  work= "done";
  ready=true; 
}

int main(){
  std::thread prod(producer);
  std::thread con(consumer);
  prod.join(); 
  con.join();
}

 

Die Ausgabe des Programms ist kurz uns prägnant, aber dennoch interessant.

producerConsumer

Dank der sequenziellen Konsistenz ist der Programmlauf vollkommen deterministisch. Das Programm gibt immer "done" aus.

Die Graphik bringt es auf den Punkt. Der Consumer-Thread wartet in der while-Schleife, bis die atomare Variable ready den Wert true besitzt. Ist dies der Fall, fährt der Consumer Thread mit seiner Arbeit fort

 SequenzielleKonsistenz

Dass das Programm immer "done" ausgibt, lässt sich einfach begründen. Ich nütze dazu die zwei Eigenschaften der sequenziellen Konsistenz aus. Zum einen werden die Anweisungen beider Threads in Sourcecodereihenfolge ausgeführt, zum andern sehen die Threads die Anweisungen des anderen Threads in der gleichen Reihenfolge. Damt folgen alle Operationen dem globalem Takt. Diesem Takt  folgt auch - mit Hilfe der while (!ready.load()){}-Schleife -  die Synchronisation des Producer-Threads mit dem Consumer-Thread .

Es geht aber auch deutlich formaler. In der Begrifflichkeit des Speichermodells lautet die Argumentationskette:

=> Steht für die Schlussfolgerung in den nächsten Zeilen.

    1. work= "done"  ist sequenced-before ready=true => work= "done" happens-before ready=true
    2. while(!ready.load()){} ist sequenced-before std::cout<< work << std::end l =>  while(!ready.load()){} happens-before std::cout<< work << std::endl
    3. ready=true  synchronizes-with while(!ready.load()){} => ready= true inter-thread happens-before while (!ready.load()){} => ready= true happens-before while (!ready.load()){}

=> Da die happens-before Relation transitiv ist, gilt: work= "done" happens-before ready= true happens-before while(!ready.load()){} happens-before std::cout<< work << std::endl

Von der Sequenzielle Konsistenz zur Acquire-Release-Semantik

Ein Thread sieht die Operationen eines anderen Threads und somit aller Threads in der gleichen Reihenfolge. Diese elemente Eigenschaft der sequenziellen Konsistenz gilt nicht mehr, wenn wir statt der sequenziellen Konsistenz die Acquire-Release Semantik für atomare Operationen auswählen. Hier geht C++ deutlich weiter als C# oder auch Java. Leider verlassen wir nun auch den Raum unserer natürlichen Intuition.

Bei der Acquire-Release Semantik findet die Synchronisation nicht zwischen Threads, sondern zwischen atomaren Variablen der Threads statt. So synchronisiert sich eine Schreib-Operation eines Threads mit einer Lese-Operation eines anderen Threads auf der gleichen atomaren Variable. Diese Synchronisationsbeziehungen auf der gleichen atomaren Variablen helfen, happens-before Relation zwischen atomaren Variablen und damit zwischen Threads zu erzeugen.

Wie geht's weiter?

Die Details zur Acquire-Release Semantik zusammen mit dem optimierten Spinlock aus dem Artikel  Das atomare Flag folgen im nächsten Artikel.

 

 

 

 

 

 

 

title page smalltitle page small Go to Leanpub/cpplibrary "What every professional C++ programmer should know about the C++ standard library".   Hole dir dein E-Book. Unterstütze meinen Blog.

 

 

 

 

Kommentare   

0 #71 Alvaro 2017-07-29 23:27
I like the article
Zitieren
0 #72 Wilmer 2017-07-30 00:17
Thanks, it's quite informative
Zitieren
0 #73 Gavin 2017-07-30 08:02
Thanks, it's very informative
Zitieren
0 #74 Terrell 2017-08-02 07:29
Thanks for the terrific post
Zitieren

Kommentar schreiben


Abonniere den Newsletter (+ pdf Päckchen)

Beiträge-Archiv

Sourcecode

Neuste Kommentare