Linux (bibliotecas de rede muduo): 04 --- Passe resumo Sincronização do (pacote MutexLock, MutexLockGuard, Condição)

  • Neste artigo convergência no artigo anterior (mutex, uma variável de condição, fechaduras, semáforos, o sono escrevem leitura) : https://blog.csdn.net/qq_41453285/article/details/104859230
  • MutexLock, MutexLockGuard, classe Estado, etc. O código completo pode ser encontrado em muduo / base nestes classe não estão autorizados a construtor de cópia e atribuição

A, MutexLock, pacote MutexLockGuard

  • MutexLock: Embalagem região crítica (seção crítica), este é um recurso simples, com um pacote exclusivo para criar técnicas de RAII e destruídos. MutexLock membros de dados geral de outra classe
    • A zona crítica no Windows CRITICAL_SECTION struct, é reentrante
    • Sob Linux é pthread_mutex_t, padrão não é reentrante
  • MutexLockGuard: entrar e sair da secção crítica do pacote, ou seja, de bloqueio e de desbloqueio. MutexLockGuard geral é no objeto pilha, o seu âmbito é exatamente igual à região crítica

MutexLock

  • Descrição:
    • MutexLock valor acrescentado na medida em que proporciona a função de isLockedByThisThread () para as afirmações do programa
    • Sobre a função tid (), mais adiante neste artigo iremos detalhar "identificador segmento Linux"
  • Código é a seguinte:
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 é a seguinte:
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");
  •  Note que o código acima é a última linha define uma macro, o programa macro, a fim de evitar que tais erros aparecem abaixo:
void doit()
{
    //错误,产生一个临时对象,互斥器创建之后立马又销毁了,下面的临界区没有锁住
    MutexLockGuard(mutex);
    //正确的做法要加上变量名,例如:MutexLockGuard lock(mutex)
    
    //...临界区
}
  • precauções:
    • Alguém MutexLockGuard modelo de escrita, onde não fazê-lo porque o tipo de modelo parâmetro MutexLock único possível , não há necessidade de aumentar a flexibilidade arbitrariamente, então eu coloquei manualmente o modelo instanciado (instanciar) um
    • Além disso, uma formulação mais agressivo é, o bloqueio / desbloqueio para a área privada, e depois MutexLockGuard para um amigo MutexLock de. Eu penso nos comentários para informar o programador, o outro antes do check-in de revisão de código também é muito fácil encontrar casos de uso indevido (grep getPthreadMutex)
  • Este código não atinge força industrial:
    • mutex tipo criado PTHREAD_MUTEX_DEFAULT, ao invés do que esperávamos tipo PTHREAD_MUTEX_NORMAL (na verdade, ambas são susceptíveis de ser idênticos), uma abordagem rigorosa é usar mutexattr para indicar o tipo de mutex especificado (atributos mutex pode ser encontrado em: https: // blog.csdn.net/qq_41453285/article/details/90904833 )
    • Não verificar o valor de retorno. Aqui não () para verificar o valor de retorno assert, desde assert () na compilação de lançamento foi a declaração vazia . Nós verificar o significado valor de retorno é para evitar deficiências ENOMEM tais recursos, que geralmente ocorrem no programa de produtos muito carregado. Uma vez que este erro, o programa deve ser limpo imediatamente e tomar a iniciativa de retirar-se da cena, caso contrário ele irá de alguma forma entrar em colapso, a investigação posterior difícil. Aqui temos de afirmar não-debug, talvez google-GLOG o CHECK () macro é uma boa idéia
  • Algumas outras idéias:
    • Uma biblioteca de recurso muduo é apenas o mais comum e as funções mais básicas, em particular, pretende-se evitar a prestação de uma variedade de funções escolha semelhante. muduo não um "supermercado" e branco não iria indiscriminada, para uma variedade de balanço útil e características inúteis completo colocar para fora. muduo Shanfanjiujian, encolhe os ombros, reduzindo escolha, a vida mais simples
    • MutexLock não fornecer trylock função (), porque não têm utilizado no código gerada. Eu não posso pensar quando os procedimentos precisam de "tentar bloquear um bloqueio," Talvez eu escrevi o código é muito simples (use um trylock é usado para observar contenção de bloqueio, consulte [RWC] "Considere usar nonblocking sincronização rotinas para monitorar contenção ")

Dois, pacote de Condição

  • variável de condição (variável de condição) permite que a espera () quando o mutex especificado
  • Sobre o porquê desta classe o seu próprio pacote Estado:
    • Mas eu não consigo pensar em qualquer razão para que uma variável de condição será usado em conjunto com mutex diferente . condição intrínseca classe e Condição de Java não suportam, então eu acho que pode dar-se esta flexibilidade, honestamente bom
    • Em vez disso, boost :: fio de mutex condition_variable é especificado no momento da espera, visite o complexo desenho de suas primitivas de sincronização:
      • Conceito有四种: bloqueável, TimedLockable, SharedLockable, UpgradeLockable
      • Bloqueio有六种: lock_guard, unique_lock, shared_lock, upgrade_lock, upgrade_to_unique_lock, scoped_try_lock
      • Mutex有七种: exclusão mútua, try_mutex, timed_mutex, recursive_mutex, recursive_try_mutex, recursive_timed_mutex, shared_mutex
    • Eu tenho medo estúpido, para ver tal um barulho biblioteca boost :: discussão, eu tinha três desvio inclinada. Infelizmente tópicos biblioteca C ++ 11 também adoptaram este esquema . O nome da classe é também não faz sentido, por que não ser honesto com nomes populares, tais readers_writer_lock isso? Tem que aumentar a carga mental, tinha inventado um novo nome. Eu não quero pagar o preço por essa flexibilidade, preferiria fazer algumas simples para ver para entender a classe para uso , "rodas" de que algumas linhas simples de código feito feito de qualquer maneira. Claro, é a capacidade de fornecer flexibilidade, mas a flexibilidade não é necessária quando o código é escrito mortos, mais precisa de grande sabedoria

Condição

  • A classe a seguir muduo :: Condição simplesmente encapsula variável de condição, também é fácil de usar
  • Sobre regras de nomeação função de membro:
    • Aqui com notificar / notifyAll como um nome de função, porque há outros significados sinalizar, C ++ no sinal / slot, C e assim por diante na signalhandler
    • Eu não acho que o conflito, nós próprios define o nome destas funções membro
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_;
};

Use em variáveis ​​de condição e de mutex

  • Se você quiser incluir um MutexLock classe e condição, deve prestar atenção à ordem de sua seqüência de declaração e inicialização:
    • construção MutexLock deve preceder Condição
    • Condição para inicializar e MutexLock
  • Por exemplo na sequência de um (contagem) classe um CountDownLatch:
class CountDownLatch
{
public:
    //构造函数中,初始化顺序要与声明顺序一致
    //并且使用mutex_初始化conditon_
    CountDownLatch(MutexLock& mutex)
        :mutex_(mutex), conditon_(mutex_), count_(0) {}
private:
    MutexLock& mutex_;   //互斥器先于条件变量定义
    Condition conditon_;
    int count_;
};

Em terceiro lugar, o resumo

  • Deixe-me enfatizar novamente, apesar de ter levado um monte de espaço neste capítulo descreve como usar o mutex e variável de condição corretamente, mas isso não significa que eu incentivar usá-los em todos os lugares:
    • Ambos são primitivas de sincronização de nível muito baixo , usado principalmente para mais avançada ferramenta de programação concorrente
    • A programas multi-threaded para sincronizar se uso pesado mutex e variável de condição, com árvores lápis faca básica serrar (Meng linguagem Yan) não tem distinção
  • No programa usando a biblioteca Pthreads tem um benefício adicional: ferramentas de análise de reconhecê-los, entender sua semântica . Análise Enfiar Ferramentas como o Intel Thread Checker e Valgrind-Helgrind 33 e assim ser capaz de identificar PThreads chamadas, e de acordo acontece-antes de relacionamento (ver: http://research.microsoft.com/en-us/um/people/lamport/pubs/time -clocks.pdf ) se o programa de análise de dados de corrida

Em quarto lugar, adicional

Lançado 1525 artigos originais · ganhou elogios 1084 · Vistas 450.000 +

Acho que você gosta

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