Espacios de nombres
Variantes
Acciones

std::scoped_lock

De cppreference.com
< cpp‎ | thread
 
 
Biblioteca de apoyo de concurrencia
Hilos
(C++11)
(C++20)
Espacio de nombres this_thread
(C++11)
(C++11)
(C++11)
Cancelación cooperativa
Exclusión mutua
(C++11)
Gestión genérica de bloqueo
(C++11)
(C++11)
scoped_lock
(C++17)
(C++11)
(C++11)
(C++11)
Variables de condición
(C++11)
Semáforos
Pestillos y barreras
(C++20)
(C++20)
Futuros
(C++11)
(C++11)
(C++11)
(C++11)
Recuperación segura
(C++26)
Punteros de riesgo
Tipos atómicos
(C++11)
(C++20)
Inicialización de tipos atómicos
(C++11)(en desuso en C++20)
(C++11)(en desuso en C++20)
Orden de memoria
Funciones independientes para operaciones atómicas
Funciones independientes para indicadores atómicos
 
 
Definido en el archivo de encabezado <mutex>
template< class... MutexTypes >
class scoped_lock;
(desde C++17)

La clase scoped_lock es una envoltura de mutex que proporciona un mecanismo conveniente estilo RAII para poseer uno o más mutexes durante la duración del ámbito de un bloque.

Cuando se crea un objeto scoped_lock, intenta tomar posesión de los mutexes que se le asignan. Cuando el control abandona el ámbito en el que se creó el objeto scoped_lock, el scoped_lock se destruye y los mutexes se liberan, en orden inverso. Si se dan varios mutexes, el algoritmo de evitación de interbloqueo se usa como si lo hiciera std::lock.

La clase scoped_lock no se puede copiar.

Contenido

[editar] Parámetros de plantilla

MutexTypes - Los tipos de los mutexes a bloquear. Los tipos deben cumplir con los requerimientos de Lockable a menos que sizeof...(MutexTypes)==1, en cuyo caso el tipo único debe cumplir con los requerimientos de BasicLockable

[editar] Tipos miembro

Tipo miembro Definición
mutex_type (if sizeof...(MutexTypes)==1) Mutex, el único tipo en MutexTypes...

[editar] Funciones miembro

Construye un objeto scoped_lock, opcionalmente bloqueando los mutexes dados
(función miembro pública) [editar]
Destruye el objeto scoped_lock object, desbloquea los mutexes subyacentes
(función miembro pública) [editar]
operator=
[eliminada]
No es asignable por copia
(función miembro pública) [editar]

[editar] Ejemplo

El siguiente ejemplo utiliza std::scoped_lock para bloquear pares de mutexes sin bloqueo mutuo y es estilo RAII.

#include <mutex>
#include <thread>
#include <iostream>
#include <vector>
#include <functional>
#include <chrono>
#include <string>
 
struct Employee {
    Employee(std::string id) : id(id) {}
    std::string id;
    std::vector<std::string> lunch_partners;
    std::mutex m;
    std::string output() const
    {
        std::string ret = "Empleado " + id + " tiene compañeros de almuerzo: ";
        for( const auto& partner : lunch_partners )
            ret += partner + " ";
        return ret;
    }
};
 
void send_mail(Employee &, Employee &)
{
    // simular una operación de mensajeo que consume tiempo
    std::this_thread::sleep_for(std::chrono::seconds(1));
}
 
void assign_lunch_partner(Employee &e1, Employee &e2)
{
    static std::mutex io_mutex;
    {
        std::lock_guard<std::mutex> lk(io_mutex);
        std::cout << e1.id << " y " << e2.id << " a la espera de cerrojos" << std::endl;
    }
 
    {
        // usar std::scoped_lock para adquirir dos cerrojos sin preocuparse deabout 
        // otras llamadas a assign_lunch_partner interbloquándonos
        // y también proporciona un mecanismo estilo RAII conveniente
 
        std::scoped_lock lock(e1.m, e2.m);
 
        // Código equivalente 1 (usando std::lock y std::lock_guard)
        // std::lock(e1.m, e2.m);
        // std::lock_guard<std::mutex> lk1(e1.m, std::adopt_lock);
        // std::lock_guard<std::mutex> lk2(e2.m, std::adopt_lock);
 
        // Código equivalente 2 (si se necesirtan unique_locks, p. ej., para variables de condición)
        // std::unique_lock<std::mutex> lk1(e1.m, std::defer_lock);
        // std::unique_lock<std::mutex> lk2(e2.m, std::defer_lock);
        // std::lock(lk1, lk2);
        {
            std::lock_guard<std::mutex> lk(io_mutex);
            std::cout << e1.id << " y " << e2.id << " adquirieron cerrojos" << std::endl;
        }
        e1.lunch_partners.push_back(e2.id);
        e2.lunch_partners.push_back(e1.id);
    }
 
    send_mail(e1, e2);
    send_mail(e2, e1);
}
 
int main()
{
    Employee alice("alice"), bob("bob"), christina("christina"), dave("dave");
 
    // asignar en hilos paralelos porque enviar correo a los usuarios
    // sobre sus compañeros asignados se lleva mucho tiempo
    std::vector<std::thread> threads;
    threads.emplace_back(assign_lunch_partner, std::ref(alice), std::ref(bob));
    threads.emplace_back(assign_lunch_partner, std::ref(christina), std::ref(bob));
    threads.emplace_back(assign_lunch_partner, std::ref(christina), std::ref(alice));
    threads.emplace_back(assign_lunch_partner, std::ref(dave), std::ref(bob));
 
    for (auto &thread : threads) thread.join();
    std::cout << alice.output() << '\n'  << bob.output() << '\n'
              << christina.output() << '\n' << dave.output() << '\n';
}

Posible salida:

alice y bob a la espera de cerrojos
alice y bob adquirieron cerrojos
christina y bob a la espera de cerrojos
christina y alice a la espera de cerrojos
dave y bob a la espera de cerrojos
dave y bob adquirieron cerrojos
christina y alice adquirieron cerrojos
christina y bob adquirieron cerrojos
Empleado alice tiene compañeros de almuerzo: bob christina 
Empleado bob tiene compañeros de almuerzo: alice dave christina 
Empleado christina tiene compañeros de almuerzo: alice bob 
Empleado dave tiene compañeros de almuerzo: bob

[editar] Informes de defectos

Los siguientes informes de defectos de cambio de comportamiento se aplicaron de manera retroactiva a los estándares de C++ publicados anteriormente.

ID Aplicado a Comportamiento según lo publicado Comportamiento correcto
LWG 2981 C++17 Se proporcionó guía de deducción redundante de scoped_lock<MutexTypes...>. Se eliminó.

[editar] Véase también

Implementa un envoltorio de propiedad de mutex movible.
(plantilla de clase) [editar]
Implementa un envoltorio de propiedad de mutex estrictamente basado en un ámbito.
(plantilla de clase) [editar]