boost::shared_mutex
oder std::shared_mutex
(C++ 17) kann für einzelne Writer, mehrere Leser Zugriff verwendet werden. Als Bildungsübung habe ich eine einfache Implementierung zusammengestellt, die Spinlocking verwendet und andere Einschränkungen (z. B. Fairness-Richtlinie) hat, aber offensichtlich nicht für die Verwendung in realen Anwendungen gedacht ist.C++ shared_mutex Implementierung
Die Idee ist, dass der Mutex eine Referenzzählung behält, die Null ist, wenn kein Thread die Sperre hält. Wenn> 0, repräsentiert der Wert die Anzahl der Leser, die Zugriff haben. Wenn -1, hat ein einzelner Schreiber Zugriff.
Ist dies eine korrekte Implementierung (insbesondere bei den verwendeten, minimalen, Speicherbestellungen), die frei von Datenrennen ist?
#include <atomic>
class my_shared_mutex {
std::atomic<int> refcount{0};
public:
void lock() // write lock
{
int val;
do {
val = 0; // Can only take a write lock when refcount == 0
} while (!refcount.compare_exchange_weak(val, -1, std::memory_order_acquire));
// can memory_order_relaxed be used if only a single thread takes write locks ?
}
void unlock() // write unlock
{
refcount.store(0, std::memory_order_release);
}
void lock_shared() // read lock
{
int val;
do {
do {
val = refcount.load(std::memory_order_relaxed);
} while (val == -1); // spinning until the write lock is released
} while (!refcount.compare_exchange_weak(val, val+1, std::memory_order_acquire));
}
void unlock_shared() // read unlock
{
refcount.fetch_sub(1, std::memory_order_relaxed);
}
};
Ich war mir nicht sicher über die Speicherreihenfolge in unlock_shared, aber meine Argumentation war, dass es wirklich nichts "freigibt", da es nur Lesezugriff hat und die Daten nicht ändern kann. – LWimsey
@LWimsey: Ja, es ist schwieriger über die Bestellung von Ladungen nachzudenken, als die Bestellung von Geschäften, aber es ist eine echte Sache. Eine Ladung wird global sichtbar, wenn Daten aus dem L1-Cache gelesen werden. (Da wird dann eine Kopie vom global-kohärenten Cache in den Out-of-Order-Core einer einzelnen CPU kopiert.) –