Es kommt ganz drauf an wie man das umsetzt.
Ich mache es so, das ich 2 Listen habe (empty und partial) und mit der partial Liste anfange und versuche das erste Element zu entfernen, dass mache ich solange bis das geklappt hat oder die Liste leer ist (es wird also immer die ganze Liste gelockt um das erste Element zu entfernen).
So kommt es zwar vor, dass ich soviele partial+empty Listen wie CPUs habe, aber das ist eher unwahrscheinlich und da die meisten Objekte eh nur nen Cache mit einer Page haben ist das auch nicht weiter schlimm.
Dann kommt noch hinzu, dass ich noch eine Ebene darüber habe, sprich das ich pro CPU noch nen Stack mit 4 Objekten habe und erstmal der benutzt wird.
Will ich einen Cache komplett löschen, locke ich die komplette Liste (in dem Fall die free) und entferne halt wieder das erste Element und kann dann den Cache freigeben ohne das es Probleme gibt. Das wiederhole ich solange bis die Liste leer ist.
Man kann das ganze natürlich auch noch mit Lock-free Algos implementieren, aber ob es das wirklich so bringt, wage ich doch zu bezweifeln, lasse mich aber gerne eines besseren belehren. Denn das Entfernen des ersten Elements aus einer Liste ist nun wirklich keine "lange" Angelegenheit.
Problematisch an meiner Variante ist "nur", dass durch das "ständige" Entfernen und Einfügen natürlich mehr Schreibzugriffe stattfinden als eventuell notwendig wären. Ob das wirklich ein Problem ist, kann ich aber nicht sagen.
@taljeth
Wenn ich an einer Taskstruktur arbeite, locke ich aber die Taskstruktur und nicht das Blatt! Das ist bei mir schon ein Unterschied. Es ging mir eigentlich nur darum, das sich die Position im Baum nicht verändern kann und nur wenn das geschiet, muss halt der Baum gelockt werden. Zumal man dann auch noch zw. Bäumen und Bäumen
unterscheiden muss. Wenn bei nem einfachen binär Baum ein Blatt gelöscht wird, geht das ja noch, aber z.B. bei nem AVL-Baum kann das den ganzen Weg zurück zur Wurzel verändern, da finde ich es dann sinnvoller (und einfacher) den ganzen Baum zu locken.