Linux (bibliotecas de red muduo): 04 --- Thread Resumen de sincronización de la (paquete MutexLock, MutexLockGuard, Condición)

  • En este artículo convergencia en el artículo anterior (mutex, una condición variable, cerraduras, semáforos, dormir lectura-escritura) : https://blog.csdn.net/qq_41453285/article/details/104859230
  • MutexLock, MutexLockGuard, clase Condiciones, etc. El código completo se puede encontrar en muduo / base en estas clases no pueden constructor de copia y asignación

A, MutexLock, paquete MutexLockGuard

  • MutexLock: Embalaje región crítica (sección crítica), se trata de un recurso sencillo con un paquete exclusivo para crear técnicas RAII y destruido. miembros de datos generales MutexLock de otra clase
    • La zona crítica en CRITICAL_SECTION estructura de Windows, es reentrante
    • Bajo Linux es pthread_mutex_t, por defecto no es reentrante
  • MutexLockGuard: entrar y salir de la sección crítica del paquete, a saber, el bloqueo y desbloqueo. MutexLockGuard general es en el objeto pila, su alcance es exactamente igual a la región crítica

MutexLock

  • Descripción:
    • MutexLock valor añadido, ya que proporciona la función isLockedByThisThread () para las afirmaciones de programa
    • Acerca de la función tid (), más adelante en este artículo detallaremos "identificador de hebra Linux"
  • Código es el siguiente:
class MutexLock :boost::noncopyable
{
public:
    MutexLock() :holder_(0)
    {
        pthread_mutex_init(&mutex_, NULL);
    }

    ~MutexLock()
    {
        assert(holder_ == 0);
        pthread_mutex_destory(&mutex_);
    }

    bool isLockByThisThread()
    {
        return holder_ == CurrentThread::tid();
    }

    void assertLocked()
    {
        assert(isLockByThisThread());
    }

    //仅供MutexLockGuard调用,严禁用户代码调用
    void lock()
    {
        //这两行顺序不能反
        pthread_mutex_lock(&mutex_);
        holder_ = CurrentThread::tid();
    }
    //仅供MutexLockGuard调用,严禁用户代码调用
    void unlock()
    {
        holder_ = 0;
        pthread_mutex_unlock(&mutex_);
    }

    //仅供Condition调用,严禁用户代码调用
    pthread_mutex_t* getPthreadMutex()
    {
        return &mutex_;
    }
private:
    pthread_mutex_t mutex_;
    pid_t holder_;
};

MutexLockGuard

  • Código es el siguiente:
class MutexLockGuard :boost::noncopyable
{
public:
    explicit MutexLockGuard(MutexLock& mutex):mutex_(mutex)
    {
        mutex_.lock();
    }

    ~MutexLockGuard()
    {
        mutex_.unlock();
    }
private:
    MutexLock& mutex_;
};

#define MutexLockGuard(x) static_assert(false,"missing mutex guard var name");
  •  Tenga en cuenta que el código anterior es la última línea define una macro, el programa macro con el fin de evitar este tipo de errores aparecen a continuación:
void doit()
{
    //错误,产生一个临时对象,互斥器创建之后立马又销毁了,下面的临界区没有锁住
    MutexLockGuard(mutex);
    //正确的做法要加上变量名,例如:MutexLockGuard lock(mutex)
    
    //...临界区
}
  • precauciones:
    • Alguien MutexLockGuard plantilla por escrito, en la que no lo hizo porque el tipo de plantilla parámetro MutexLock único posible , sin necesidad de aumentar la flexibilidad de manera arbitraria, por lo que poner manualmente la plantilla de instancia (instantiate) una
    • Además una redacción más agresivo es, el bloqueo / desbloqueo en el espacio privado, y luego MutexLockGuard a un amigo MutexLock de. Creo que en los comentarios de informar al programador, la otra antes de que el registro de entrada en la revisión de código también es muy fácil de encontrar casos de uso indebido (grep getPthreadMutex)
  • Este código no alcanza la fuerza industrial:
    • mutex tipo PTHREAD_MUTEX_DEFAULT creado, en lugar de lo que esperábamos tipo PTHREAD_MUTEX_NORMAL (de hecho, ambos son casi idénticos), un enfoque estricto es utilizar mutexattr para indicar el tipo de la exclusión mutua especificado (atributos de exclusión mutua se pueden encontrar en: https: // blog.csdn.net/qq_41453285/article/details/90904833 )
    • No comprobar el valor de retorno. Aquí no () para comprobar la aserción valor de retorno, ya que afirman () en la versión de lanzamiento fue comunicado vacío . Comprobamos el significado valor de retorno es para prevenir deficiencias ENOMEM dichos recursos, que generalmente ocurren en el programa de productos muy cargado. Una vez que este error, el programa debe limpiarse inmediatamente y tomar la iniciativa de retirarse de la escena, de lo contrario, de alguna manera colapsar, a la investigación posterior difícil. Aquí tenemos que afirmar no depuración, tal vez google-GLog el cheque () macro es una buena idea
  • Algunas otras ideas:
    • Una biblioteca de operaciones muduo sólo es la más común y la mayoría de las funciones básicas, en particular, se tiene la intención de evitar proporcionar una variedad de funciones de decisión similar. muduo no un "supermercado" y Blanca no indiscriminada, a una variedad de características útiles e inútiles pleno rendimiento apaga. muduo Shanfanjiujian, se encoge de hombros, la elección de reducción, la vida más fácil
    • MutexLock no proporciona trylock función (), porque yo no lo he utilizado en el código generado. No se me ocurre cuando los procedimientos tienen que "tratar de bloquear un bloqueo," Tal vez he escrito el código es demasiado simple (utilizar un trylock se utiliza para observar la contención de bloqueo, véase [RWC] "Considere el uso de sincronización no bloqueantes rutinas para el monitor contención ")

Dos, el paquete Condición

  • condición variable (variable de condición) permite a la espera () cuando el mutex especificada
  • Acerca de por qué esta clase su propio paquete Estado:
    • Pero yo no puedo pensar en ninguna razón para que una condición variable será utilizada en conjunto con diferentes mutex . intrínseca condición de clase y condición de Java no son compatibles, por lo que creo que podemos renunciar a esta flexibilidad, honestidad buena
    • En cambio, impulso :: hilo de exclusión mutua condition_variable se especifica en el momento de espera, por favor visite el complejo diseño de sus primitivas de sincronización:
      • Concepto有四种: cerradura, TimedLockable, SharedLockable, UpgradeLockable
      • Cerradura有六种: lock_guard, unique_lock, shared_lock, upgrade_lock, upgrade_to_unique_lock, scoped_try_lock
      • Mutex有七种: mutex, try_mutex, timed_mutex, recursive_mutex, recursive_try_mutex, recursive_timed_mutex, shared_mutex
    • Yo tengo miedo estúpido, para ver como biblioteca de impulso :: hilo de un alboroto, que tenía tres desvío inclinada. Desafortunadamente hilos biblioteca de C ++ 11 también adoptaron este esquema . El nombre de la clase es también no tiene sentido, por qué no ser honesto con nombres populares, tales readers_writer_lock ella? Que aumentar la carga mental, que había inventado un nuevo nombre. Yo no quiero pagar el precio de esa flexibilidad, preferiría hacer unos simples para ver a entender la clase que se utiliza , "ruedas" que unas pocas líneas de código simple hecho lo hizo de todos modos. Por supuesto, es la capacidad de proporcionar flexibilidad, pero no es necesaria la flexibilidad en donde se escribe el código muerto, aún queda una gran sabiduría

Condición

  • La siguiente clase de muduo :: Condición simplemente encapsula variable de condición, también es fácil de usar
  • Acerca de las reglas de nomenclatura de funciones miembro:
    • Aquí con notificar / notifyAll como un nombre de la función, porque hay señal de otros significados, C ++ en la señal / ranura, C y así sucesivamente en el signalhandler
    • No creo que el conflicto, poseemos define el nombre de estas funciones miembro
class Condition :boost::noncopyable
{
public:
    explicit Condition(MutexLock& mutex) :mutex_(mutex)
    {
        pthread_cond_init(&pcond_);
    }
	~Condition()
    {
        pthread_cond_destory(&pcond_);
    }

    void wait()
    {
        pthread_cond_wait(&pcond_, mutex_.getPthreadMutex());
    }
    void notify()
    {
        pthread_cond_signal(&pcond_);
    }
    void notifyAll()
    {
        pthread_cond_broadcast(&pcond_);
    }
private:
    MutexLock& mutex_;
    pthread_cond_t pcond_;
};

Uso de variables de condición y de exclusión mutua

  • Si desea incluir una MutexLock clase y condición, debe prestar atención a la orden de su secuencia de declaración y la inicialización:
    • MutexLock construcción debe preceder Condición
    • Condición para inicializar y MutexLock
  • Por ejemplo después de una clase un CountDownLatch (cuenta atrás):
class CountDownLatch
{
public:
    //构造函数中,初始化顺序要与声明顺序一致
    //并且使用mutex_初始化conditon_
    CountDownLatch(MutexLock& mutex)
        :mutex_(mutex), conditon_(mutex_), count_(0) {}
private:
    MutexLock& mutex_;   //互斥器先于条件变量定义
    Condition conditon_;
    int count_;
};

En tercer lugar, el resumen

  • Quiero subrayar una vez más, a pesar de que tuvo una gran cantidad de espacio en este capítulo se describe cómo utilizar el mutex y variables condición correctamente, pero eso no quiere decir que animo a usarlos en todas partes:
    • Ambos son primitivas de sincronización de muy bajo nivel , que se utilizan principalmente para la herramienta de programación concurrente más avanzado
    • A multi-hilo programas para sincronizar si el uso excesivo mutex y variables condiciones, con árboles lápiz cuchillo aserrado básica (Meng idioma Yan) carece de distinción
  • En el programa que utiliza la biblioteca Pthreads tiene un beneficio adicional: herramientas de análisis a reconocer, entender su semántica . Herramientas de análisis de roscado como Intel Thread Checker y Valgrind-Helgrind 33 y así poder identificar Pthreads llamadas, y según pasa, antes de la relación (ver: http://research.microsoft.com/en-us/um/people/lamport/pubs/time -clocks.pdf ) si el programa de análisis de datos de la raza

En cuarto lugar, adicional

Liberadas 1525 artículos originales · ganado elogios 1084 · Vistas de 450.000 +

Supongo que te gusta

Origin blog.csdn.net/qq_41453285/article/details/104875213
Recomendado
Clasificación