boost, locking und zwei kritische Ressourcen



  • Hallo,

    ich bin neu im Threading-Thema. Ich versuche, zwei kritische Ressourcen gleichzeitig zu locken. Klappt denke ich ganz gut. Dann wird ein weiterer Funktionsaufruf getätigt, in welchem wiederrum ein Lock auf dieselbe Ressource gemacht wird. Resultat ist meines logischen Verständnisses nach ein Deadlock.

    Beispiel

    int TcpHook::closesocket(SOCKET socket)
    {
    	int result = closesocketOriginal_(socket);
    
    	// Richtig so, dass der Lock erst danach beantragt wird?
    	// Oder gibt es eine Best Practice, dass der Lock ganz oben in der Funktion steht?
    	boost::lock(mutexChannels_, mutexSockets_);
    	boost::lock_guard<boost::mutex> guard(mutexChannels_, boost::adopt_lock_t());
    	boost::lock_guard<boost::mutex> guard2(mutexSockets_, boost::adopt_lock_t());
    
    	// Beantragt wiederrum einen lock auf mutexSockets_
    	// Müsste ich also einen Recursive Lock verwenden?
    	// Aber genau genommen ist es ja keine Rekursion.
    	TcpChannel *channel = GetChannelForSocket(socket);
    
    	if (channel != nullptr)
    	{
    		sockets_.erase(socket);
    		channel->OnDisconnect(socket);
    	}
    
    	return result;
    }
    

    Die essentiellen Fragen sind als Kommentare im Code-Beispiel.

    Dazu habe ich noch eine weitere Frage. Werden Locks nur im kleinsten Rahmen auf die wirklich kritische Ressource gehalten, oder sollte der Lock so lange bestehen bleiben, wie er semantisch sinnvoll ist? Beispiel: Ich hole mir einen Pointer aus einer std::map und mache einen Lock um den Vorgang des Abrufens. Danach muss ich den Pointer aber noch verwenden. Ist es nun "richtiger", den Lock bis nach der letzten Verwendung des Pointers aufrechtzuhalten? Ich denke ja, da ansonsten ein anderer Thread das Objekt, auf dass der Pointer zeigt, zerstören könnte.

    Ich danke euch schon mal!



  • theliquidwave schrieb:

    Dann wird ein weiterer Funktionsaufruf getätigt, in welchem wiederrum ein Lock auf dieselbe Ressource gemacht wird. Resultat ist meines logischen Verständnisses nach ein Deadlock.

    Steht in der Beschreibung von mutex.
    Die sind gerne auch mal so definiert, daß man innerhalb desselben Threads ruhig öfter locken darf, damit man genau das machen kann, was Du machst. Es müssen ja nur fremde Threads blocken, die auf dieselbe Ressource zugreifen wollen, die Du Dir schon geschnappt hast.



  • Du musst jedes geteilte Byte schützen.
    Rekursive Sperren haben nichts mit rekursiven Funktionen zu tun.

    Warum werden Sockets geteilt? Das ist sehr fragwürdig!

    Mit deinen Funktionen kann ein Socket mehrfach und von verschiedenen Threads freigegeben werden. Ebenfalls fragwürdig.


Anmelden zum Antworten