Threadsicherheit einzelner List Einträge
-
Servus,
ich hab ne Lsite eigener Objekte. list<Foo> foolist
Ein Thread arbeitet am Letzten Element der Liste. Löscht dieses Element danach.
Ein Thread fügt nun gleichzeitig ein Element vorne an die Liste an und beschreibt es.Tritt sich das Ganze auf die Füße? Bzw. Wo kann sich das verhakeln?
Will das quasi so machen, daß ein Thread auf ein Event wartet, daß die Liste gefüllt ist. Dann ließt er das/die Element/e aus und löscht die.Ein andrer Thread ist für dsa Füllen da. Er hängt unabhängig vom anderen Thread ein Element VORNE an die Liste und setzt dann das Event.
Allerdings soll er auch anhängen können, wenn der lesende/löschende Thread gerade in der Liste unterwegs ist.
-
Hallo
Ja du must das manuell Threadsicher machen. Stichwort ist Critical Section, soetwas gibt es für die meisten Thread-Implementation/Wrapper.
bis bald
akari
-
Das Problem, das Du da beschreibst, ist recht bekannt. Und zwar unter dem Namen Producer-Consumer. Da sollte sich einiges dazu finden lassen. Eventuell kannst Du mit Hilfe von Lock-Free Datastructures auch teilweise ohne locking auskommen. Aber Vorsicht, da sollte man schon wissen was man tut, das ist nicht einfach.
edit: Probleme geben kann es, wenn der Producer mal nicht nachkommt und die Liste daher leer läuft. Dann gibt's Probleme, wenn der Producer versucht ein neues Element vor das letzte Verbleibende zu hängen und der Consumer genau dieses in dem Moment löscht.
-
@akari: Ich weiss. Aber die Frage ist wie einsetzen.
@Jesper: Genau das ist der Casus Knackus.
Also wenn ich einzelne Elemente absichere:
Die Liste ist aus Objekten einer Klasse gebaut. In der Klasse gibt es sein CriticalSection Element.
Ein schreibender Thread blockt nun das 0. Element für sich mittels Zugriff auf CriticalSection. Der Lesende und Löschende kann ja mit den andern Elementen machen was er will. Er greift ja nur auf den "next Element" Zeiger des 0. Elements zu, während der SChreibende Thread auf das "previous Element" zugreift. Die kommen sich also hier nicht in die Quere. Wenn der Löschende immer brav Lock anfordert, wird er das 0. nicht löschen, wenn der SChreibende gerade geblockt hat und quasi ein -1. ranhängt.
Das Problem wird allerdings kommen, wenn KEIN Element in der Liste ist. Da hab ich ja nix zum Blocken oO. Zack Bumm.... Wie ich DAS umgehe... Da müsste ich dann schon wieder mit einer IF arbeiten...Andre Lösung: Ich sichere einfach die komplette Liste ab. Aber das kostet mich Performance. DEnn wenn ein schreibender Thread die Liste blockiert, kann der Lesende nicht zugreifen. DAmit blockiere ich die komplette Liste. Genauso kann kein Thread schreiben, wenn der Lesende gerade liest. Diese Lösung würde mich also nahe daran führen, statt einer Liste für meine DAten einfach eine Membervariable zu verwenden. Die Variable wird so lange geblockt bis sie ausgelesen wurde... Ich finde allerdings nicht, daß das die schnelle Lösung ist... Damit mache ich meine ganze wweitere Ausführung vom Lesen Thread abhängig.
Dummerweise muss der ganze Vorgang so aufgebaut sein, daß der die schreibenden Threads so wenig wie möglich bremst... Hmmm.... Soll ich eventuell einen Ringspeicher machen? Lesender Thread kommt vom letzten gelesenen Element und liesst bis zum letzten geschriebenen. SChreibender schreibt vom letzten geschriebenen. Hmmm DA ist dann die Frage wie mach ich das wenn mehrere SChreiben wollen... Blocken... Wer schreibt macht das Tor zu. Die andern schriebenden haben dann eben "Öi du komms hier nich rein".
-
Hallo Shogun,
ich glaube dass hier ein Beispiel-Code ist, der Deinem Problem schon recht nahe kommt. Der setzt aber boost.thread voraus; kann ich aber sowieso nur empfehlen.
Gruß
Werner
-
Habe ich zwei Tage versucht unter BCB 2006 zum Laufen zu kriegen. Keine Chance. Damit wollte ich ganz zu Anfang meine Threads und so machen.
-
Der Code lockt aber auch die ganze Liste. Das sollte ja hier vermieden werden.
-
Meinst du jetzt boost::thread? Hast du da schon die 1.34.0 probiert? Die kennt den BCB2006 schon.
Mit etwas Arbeit bekommt man aber auch die 1.33.1 zum Laufen.
-
Die 1.34 noch nicht. Das war die 1.33. Da hatte ich dann aufgegeben.
Deswegen programmiere ich nur mit der VCL. WEiss aber ned so recht ob mich der Umstieg auf die Boost jetzt zuviel Zeit kostet.
-
Du mußt halt bloß die Versionsstrings in einigen Headerdateien anpassen.
Weiterhin verwendet der BCB2006 die Dinkumware-lib. Du mußt den Compiler also hier so wie einen BCB5 behandeln (der hatte RougeWave). Beim BCB6 (STLPort) kam noch ein Präfix dazu. Was genau ich da geändert hatte habe ich mir leider nicht gemerkt. Es gab da mal einen schönen Artikel in der Borland-Knowledge-base dazu.
http://support.borland.com/thread.jspa?messageID=5725ᙝ
Auf den kann ich aber nicht mehr zugreifen. Vielleicht schaffst du das ja.Hier sind mal die Versionsstrings
BCB2007 0x0590
BDS2006 0x0582
BCB6 0x0564
BCB5 0x0551