Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Klasa scoped_lock uzyskuje co najmniej jeden mutex na budowie i uwalnia je na zniszczenie. W przypadku podania wielu muteksów algorytm unikania zakleszczenia (odpowiednik std::lock) jest używany do zapobiegania zakleszczeniom. Wprowadzono w języku C++17.
Składnia
// Single mutex type version
template <class _Mutex>
class _NODISCARD_LOCK scoped_lock<_Mutex> {
public:
using mutex_type = _Mutex;
explicit scoped_lock(_Mutex& _Mtx) : _MyMutex(_Mtx) { // construct and lock
_MyMutex.lock();
}
explicit scoped_lock(adopt_lock_t, _Mutex& _Mtx) noexcept
: _MyMutex(_Mtx) {} // construct but don't lock
~scoped_lock() noexcept {
_MyMutex.unlock();
}
scoped_lock(const scoped_lock&) = delete; // prevent creating a new scoped_lock by copying an existing one
scoped_lock& operator=(const scoped_lock&) = delete; // prevent assigning one scoped_lock to another
};
// multiple mutex types version
template <class... MutexTypes>
class scoped_lock {
explicit scoped_lock(MutexTypes&... m);
explicit scoped_lock(MutexTypes&... m, adopt_lock_t);
~scoped_lock();
scoped_lock(const scoped_lock&) = delete; // prevent creating a new scoped_lock by copying an existing one
scoped_lock& operator=(const scoped_lock&) = delete; // prevent assigning one scoped_lock to another
};
Uwagi
adopt_lock_t jest typem tagu wskazującym, że scoped_lock konstruktor powinien przyjąć własność mutexes, które są już zablokowane przez wątek wywołujący. Dzięki temu można utworzyć scoped_lock obiekt bez ponownego zablokowania muteksów, co może być przydatne w niektórych scenariuszach, w których blokady zostały już uzyskane i chcesz zarządzać ich okresem istnienia za pomocą elementu scoped_lock.
Klasa scoped_lock zarządza blokowaniem i odblokowywaniem co najmniej jednego muteksu w całym zakresie. Podczas tworzenia scoped_lock obiektu uzyskuje on własność przekazanych mutexes.
scoped_lock Gdy obiekt zostanie zniszczony (na przykład gdy wykracza poza zakres), elementy mutexes są zwalniane. Gwarantuje to, że mutexy są zawsze prawidłowo zwalniane, nawet jeśli zostanie zgłoszony wyjątek.
Jeśli musisz zablokować tylko jeden mutex, rozważ użycie polecenia lock_guard lub unique_lock. Użyj scoped_lock polecenia , jeśli musisz zablokować wiele muteksów jednocześnie bez ryzyka zakleszczenia.
Klasa scoped_lock nie jest kopiowalna.
Jeśli tylko jeden typ mutex jest przekazywany do scoped_lock, scoped_lock zapewnia alias typu o nazwie mutex_type , który odnosi się do tego jednego typu mutex. Jeśli jednak utworzysz obiekt z co najmniej dwoma scoped_lock typami mutex, alias nie istnieje, ponieważ mutex_type ma sens tylko wtedy, mutex_type gdy istnieje jeden podstawowy typ mutexu. W przypadku wielu muteksów nie ma jednego typu mutex do uwidocznienia.
Konstruktory
| Konstruktor | Opis |
|---|---|
scoped_lock(MutexTypes&... m) |
scoped_lock Tworzy obiekt i blokuje wszystkie dostarczone mutexy. Jeśli podano wiele muteksów, są one zablokowane przy użyciu algorytmu unikania zakleszczenia. |
scoped_lock(MutexTypes&... m, adopt_lock_t) |
scoped_lock Tworzy obiekt i przyjmuje własność dostarczonych mutexes, które muszą być już zablokowane przez wątek wywołujący. |
Destruktor
| Destruktor | Opis |
|---|---|
~scoped_lock() |
scoped_lock Niszczy obiekt i zwalnia wszystkie należące do niego mutexes. |
Przykład
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
std::mutex mutex1;
std::mutex mutex2;
int shared_data1 = 0;
int shared_data2 = 0;
void update_both(int iterations)
{
for (int i = 0; i < iterations; ++i)
{
// Lock both mutexes simultaneously without risk of deadlock
std::scoped_lock lock(mutex1, mutex2);
++shared_data1;
++shared_data2;
}
}
int main()
{
std::vector<std::thread> threads;
for (int i = 0; i < 4; ++i)
{
threads.emplace_back(update_both, 1000);
}
for (auto& t : threads)
{
t.join();
}
std::cout << "shared_data1: " << shared_data1 << '\n';
std::cout << "shared_data2: " << shared_data2 << '\n';
// Output:
// shared_data1: 4000
// shared_data2: 4000
}
Wymagania
Nagłówek:<mutex>
Przestrzeń nazw: std