- 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
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