Jest to rodzaj pytania, na które instrukcje drukowania mogą naprawdę pomóc. Na przykład:
#include <mutex>
#include <iostream>
std::mutex mut;
template <class Mutex>
class Lock
{
Mutex& mut_;
public:
~Lock()
{
std::cout << "unlock\n";
mut_.unlock();
}
Lock(const Lock&) = delete;
Lock& operator=(const Lock&) = delete;
Lock(Mutex& mut)
: mut_(mut)
{
mut_.lock();
std::cout << "lock\n";
}
};
struct A
{
~A()
{
std::cout << "~A() : " << this << "\n";
}
A()
{
std::cout << "A() : " << this << "\n";
}
A(const A& a)
{
std::cout << "A(const A&) : " << this << ", " << &a << "\n";
}
A& operator=(const A& a)
{
std::cout << "A& operator=(const A&) : " << this << ", " << &a << "\n";
return *this;
}
};
A a;
A
get()
{
Lock<std::mutex> lk(mut);
return a;
}
int
main()
{
std::cout << "Start\n";
auto vec = get();
std::cout << "End\n";
}
dokonując własną wersję std::lock_guard
mogę wstawić sprawozdań z tuszem, aby dowiedzieć się, kiedy mutex zostanie zablokowane i odblokowane. .
I poprzez fałszywy std::vector
(tzw A
powyżej), mogę wstawić sprawozdań z tuszem do specjalnego członków, że jestem zainteresowany Dla mnie to wyjścia:
A() : 0x10fcfb188
Start
lock
A(const A&) : 0x7fff4ff06b28, 0x10fcfb188
unlock
End
~A() : 0x7fff4ff06b28
~A() : 0x10fcfb188
który wyraźnie pokazuje, że mutex jest zablokowany podczas kopiowania A
z 0x10fcfb188.
Test może być zmienione dla funkcja:
int
main()
{
A vec;
std::cout << "Start\n";
vec = get();
std::cout << "End\n";
}
które obecnie wyjść:
A() : 0x10d8a7190
A() : 0x7fff5235ab28
Start
lock
A(const A&) : 0x7fff5235ab18, 0x10d8a7190
unlock
A& operator=(const A&) : 0x7fff5235ab28, 0x7fff5235ab18
~A() : 0x7fff5235ab18
End
~A() : 0x7fff5235ab28
~A() : 0x10d8a7190
Na pierwszy rzut oka wydaje się jak następuje przypisanie zewnątrz zamka, a więc wygląda na niebezpieczne. Jednak po bliższej inspekcji widzi się, że chroniony A
przy 0x10d8a7190 jest kopiowany do tymczasowego A
wewnątrz zamka. Muteks zostanie odblokowany, a zadanie zostanie zmienione z tymczasowego na lokalne. Żaden inny wątek nie mógłby odwoływać się do tymczasowego. Tak długo jak żaden inny wątek nie odwołuje się do vec
, jest to znów bezpieczne.
Kopiowanie konstrukcji 'vec' odbywa się poza blokadą. Jeśli inne wątki mogłyby modyfikować wektor referencyjny, masz wyścig danych. – Casey
To nie zadziała, zwracasz jakiś stan wewnętrzny ('m_value') przez odniesienie. –
@ DieterLücking: rzeczywiście, zauważyłem to podczas dodawania kodu właściwie ^^ 'Nawet jeśli m_value jest członkiem (tak powinno działać), zwracanie przez wartość rozwiązuje mój problem (mimo że nadal potrzebuję korzystać z lock_guard). To, co dodałem, jest rzeczywiście nierealnym problemem. Dzięki. –
Korchkidu