2011-10-23 9 views
6

La mia classe ridotta, semplificata appare come segue:"nidificate" scoped_lock

class A 
{ 
    public: 
    // ... 
    methodA(); 
    methodB(); 

    protected: 
    mutable boost::mutex m_mutex; 
    sometype* m_myVar; 
} 

A::methodA(int someParam) 
{ 
    boost::mutex::scoped_lock myLock(m_mutex); 
    m_myVar->doSomethingElse(); 
} 

A::methodB(int someParam) 
{ 
    boost::mutex::scoped_lock myLock(m_mutex); 
    m_myVar->doSomething(); 
    this->methodA(someParam); 
} 

vorrei sincronizzare l'accesso su m_myVar. Quando si chiama A::methodB(), il filo scorre nella serratura con lo stesso mutex due volte e, ovviamente, blocchi sulla prima linea di A::methodA()

C'è un modo per rendere scoped_lock non bloccare il stesso filo quando passa di nuovo?

Certo, potrei semplicemente chiamare m_mutex.unlock(). Ma questo libererebbe anche gli altri thread che attendono il blocco, il che non è assolutamente quello che voglio.

Qualche idea?

migliori saluti Tobias

+8

Utilizza un 'boost :: recursive_mutex' invece di un' boost :: mutex' – BatchyX

risposta

12

Questo è ciò che boost::recursive_mutex perché consente di ottenere il blocco dalla stessa thread senza deadlock più volte. Utilizzalo al posto di boost::mutex

+1

+1: sembra che tu affermi l'ovvio: P grazie! – Atmocreations

0

È possibile utilizzare la tryLock nel Methoda se la prova non è riuscita si dovrebbe ottenere il ThreadID corrente e continuare con l'esecuzione solo se l'ID è lo stesso con threadid che gestisce il MethodB.Otherwise se la prova riesce, puoi continuare normalmente con l'esecuzione.

+1

Questa sembra una condizione di competizione in attesa di accadere. – user786653

+0

Normalmente la risposta migliore a mio avviso è il commento di BatchyX. Ma davvero non vedo alcuna condizione di gara qui. Puoi spiegarmi per favore? – AlexTheo

+0

Scusate, con più pensieri avete probabilmente ragione potrebbe essere fatto funzionare. – user786653

4

Ci sono diverse cose che puoi fare qui. È possibile utilizzare un mutex ricorsivo che può essere acquisito più volte all'interno della stessa discussione oppure è possibile dividere methodA in un metodo privato con l'implementazione e senza blocchi e un metodo pubblico che blocca e quindi chiama l'implementazione privata. Quindi methodB chiamerebbe l'implementazione interna mentre si tiene il blocco. Poiché il metodo è privato, hai il controllo su tutti gli usi e puoi assicurarti che il metodo di implementazione venga chiamato solo tenendo premuto il lucchetto.