Das ist richtig. Was Sie im ersten Fall tun, ist die Umgehung der Thread-Sicherheitsnatur von rand_r
. Bei vielen nicht threadsicheren Funktionen wird der persistente Zustand zwischen Aufrufen dieser Funktion gespeichert (z. B. der zufällige Startwert).
Mit der thread-sicheren Variante stellen Sie tatsächlich eine threadspezifische Dateneinheit (seed1
und seed2
) bereit, um sicherzustellen, dass der Status nicht zwischen Threads geteilt wird.
Denken Sie daran, dass dies die Zahlen nicht wirklich zufällig macht, es macht nur die Sequenzen unabhängig voneinander. Wenn Sie sie mit demselben Seed starten, erhalten Sie wahrscheinlich die gleiche Sequenz in beiden Threads.
Nehmen wir als Beispiel, Sie erhalten eine zufällige Reihenfolge 2, 3, 5, 7, 11, 13, 17 gegeben einen Anfangswert von 0 mit einem gemeinsamen Startwert, abwechselnd Anrufe zu rand_r
von zwei verschiedenen Threads verursachen diese:
thread 1 thread 2
<--- 2
3 --->
<--- 5
7 --->
<--- 11
13 --->
<--- 17
und das ist der beste Fall - können Sie tatsächlich feststellen, dass der gemeinsame Zustand, da die Updates auf es möglicherweise nicht atomar beschädigt wird.
Bei nicht freigegebenen Zustand (mit a
und b
, die die zwei verschiedenen Quellen der Zufallszahlen):
thread 1 thread 2
<--- 2a
2b --->
<--- 3a
3b --->
<--- 5a
5b --->
::
Einige Thread-sichere Anrufe, die Sie benötigen den Thread-spezifischen Zustand so bieten, andere Sie können unter den Covern threadspezifische Daten (mit einer Thread-ID oder ähnlichen Informationen) erstellen, sodass Sie sich nie darum kümmern müssen, und Sie können denselben Quellcode in Umgebungen mit und ohne Threads verwenden. Ich bevorzuge das letztere selbst, einfach weil es mir das Leben leichter macht.
Zusatzmaterial für editierte Frage:
> If in thread 1, I need a random number between 1 to n, should I do '(rand_r(&seed1) % (n-1)) + 1', or there is other common way of doing this?
Angenommen, Sie einen Wert zwischen 1
und n
inklusive wollen (rand_r(&seed1) % n) + 1
verwenden. Das erste Bit gibt Ihnen einen Wert von 0
bis einschließlich n-1
, dann fügen Sie 1 hinzu, um den gewünschten Bereich zu erhalten.
> Is it right or normal if the memory for the seed is dynamically allocated?
Der Samen hat hartnäckig so lange sein, wie Sie es verwenden sind. Sie könnten es dynamisch im Thread zuweisen, aber Sie könnten es auch in der Top-Level-Funktion des Threads deklarieren. In beiden Fällen müssen Sie die Adresse irgendwie an die unteren Ebenen weiterleiten (es sei denn, Ihr Thread ist nur diese eine Funktion, die unwahrscheinlich ist).
Sie könnten es entweder durch die Funktionsaufrufe weiterleiten oder irgendwie ein globales Array einrichten, wo die unteren Ebenen die richtige Startadresse finden können.
Alternativ können Sie, da Sie sowieso ein globales Array benötigen, ein globales Array mit Seeds anstelle von Seed-Adressen verwenden, die die unteren Ebenen zum Ermitteln ihres Seeds verwenden könnten.
Sie hätten wahrscheinlich (in beiden Fällen der Verwendung des globalen Arrays) eine verschlüsselte Struktur, die die Thread-ID als Schlüssel und den zu verwendenden Seed enthält. Sie müssten dann Ihre eigenerand()
Routine schreiben, die den richtigen Samen lokalisiert und rand_r()
damit genannt hat.
Diese ist warum ich Bibliothek Routinen bevorzugen, die dies unter der Decke mit Thread-spezifischen Daten tun.
danke !! Der beste Weg ist also immer unterschiedliche Samen mit unterschiedlichen Anfangswerten für verschiedene Fäden zu verwenden, oder? – derrdji
würde ich normalerweise sagen, ja. Aber es gibt Situationen, in denen Sie den Status gemeinsam haben könnten (erstes Diagramm in meiner Antwort). In diesem Fall könnten Sie die Möglichkeit der Korruption vermeiden, indem Sie 'rand_r' mit dem Status _same_ aufrufen, aber durch einen Mutex geschützt werden. Das einzige, was Sie nicht tun wollen, ist, beide Sequenzen mit dem gleichen Seed zu initialisieren, da die Sequenzen dann identisch wären. – paxdiablo
ja, danke !! Ich wollte gerade fragen, ob ich einen freigeben und den rand_r-Aufruf mit einem Mutex-Lock überwachen könnte. – derrdji