Schneller/einfacher Synchronisierungsmechanismus



  • Ich möchte eine Bibliothek die ich gerade entwerfe auch für multi-threading Anwendungen auslegen, es gibt prinzipiell nur sehr wenige Strukturen die global benutzt werden, welche ich natürlich nur synchronisiert ansprechen darf.
    Jetzt bin ich auf der Suche nach einem schnellen einfachen Synchronisierungsmenchanismus.
    Bis jetzt gibt es nur eine globale Datenstruktur welche normalerweise nur einmal zu Begin initialisiert wird und anschließend nur noch gelesen wird, d.h. es wird nur äußerst selten darauf geschrieben, das Lesen ist immer unproblematisch. Das schreiben selbst geht sehr schnell, d.h. es ist kein aufwändiger Mechanismus notwendig, der wartende Thread muss sich nicht zwingend schlafen legen.

    Was gibt es da?



  • Multiple Read, Single Write.
    In der Windows API für Vista gibts das schon pfannenfertig, sonst selber machen.
    Simon



  • Hast du da etwas mehr Informationen für mich, ich kenn mich da nicht so aus, zumindest mit den Möglichkeiten unter Windows. Ich habe zwar mal in der MSDN geschaut, aber ich kann überhaupt nicht abschätzen was sich da für meine Zwecke anbietet.







  • Danke für die Links werde sie bei Gelegenheit ausführlicher studieren, im Moment scheint das "gängige" Reader/Writer-Pattern genau meinen Wünschen zu entsprechen.



  • Wenn das Lesen recht schnell geht dann nimm einfach eine CRITICAL_SECTION. ReaderWriterLock zahlt sich da IMO nicht aus.

    Wenn das Lesen länger dauern kann, es also vorteilhaft wäre wenn mehrer Threads gleichzeitig lesen könnten, dann ja, ReaderWriterLock, bloss musst du dir sowas unter Windows selbst stricken (wer verwendet schon Vista?).
    Oder du greifst auf eine fertige Implementierung wie die in Boost.Thread zurück (ab Boost Version 1.35 bitte, die Implementierung davor ist IIRC verbuggt).



  • Möchte mich nicht ausschließlich auf Vista festlegen, also scheidet die fertige Variante aus.
    Wie lange das Lesen dauert kann ich nicht sagen, da die Struktur Funktionszeiger enthält welche vom User bereit gestellt werden, daher sollten mehrere Threads in der Lage sein diese Struktur zu lesen (dass die Funktionen in der Struktur reentrant und threadsafe sind ist Sache des Users).



  • Dann guck dir mal die 1.35 Boost an.
    BTW: bist du sicher dass es OK ist Locks zu halten während du diese Callbacks aufrufst? Oft ist das problematisch...

    Eine Alternative wären so ne Art "Connection-Points", d.h. du lässt dir vom User ein Interface geben mit intrusive Reference-Counting (ala COM). Dann machst du z.B. einfach "lock -> interface-pointer holen -> addref aufs interface -> unlock -> call interface -> release aufs interface". Dann musst du den Lock nicht halten während du die Callback Funktion ausführst, und die Zeit wird sehr kurz, wodurch du wieder einfache Mutexen (z.B. eben CRITICAL_SECTION) verwenden könntest.

    p.S.: natürlich ist das "addref aufs interface" strenggenommen auch ein Callback zum User der gemacht wird während du ein Lock hältst. Lässt sich allerdings nicht vermeiden, und bei einer einfachen Funktion wie addref kann man denke ich guten gewissens vorschreiben dass der User selbst keine Locks holen darf (um eben Deadlocks auszuschliessen). Bzw. nur Locks die dahingehend "unproblematisch" sind, d.h. die nie gehalten werden während der Client deinen Code aufruft. Und man kann da denke ich auch verlangen dass die Funktion sehr schnell zurückkommt, denn mehr als ein InterlockedIncrement bzw. InterlockedCompareExchange ist da normalerweise nicht nötig um so eine addref Funktion zu implementieren.


Anmelden zum Antworten