{"id":347,"date":"2012-12-28T22:58:37","date_gmt":"2012-12-28T21:58:37","guid":{"rendered":"http:\/\/www.steffen-liersch.de\/content\/de\/?p=347"},"modified":"2025-03-02T11:30:30","modified_gmt":"2025-03-02T10:30:30","slug":"manual-thread-synchronization","status":"publish","type":"post","link":"https:\/\/www.steffen-liersch.de\/content\/de\/2012\/12\/manual-thread-synchronization\/","title":{"rendered":"Manuelle Thread-Synchronisation"},"content":{"rendered":"<p>Die Verwendung mehrerer Abarbeitungspfade (Threads) innerhalb eines Prozesses erfordert diverse Ma\u00dfnahmen zur Thread-Synchronisation, um <a href=\"http:\/\/de.wikipedia.org\/wiki\/Race_Condition\" rel=\"noopener\">Wettlaufsituationen<\/a> auf gemeinsam genutzte Ressourcen zu unterbinden. In den meisten F\u00e4llen handelt es sich dabei um die Ressource Speicher.<!--more--><\/p>\n<h2>Die lock-Anweisung<\/h2>\n<p>Ein Quellcodebereich kann beispielsweise mit Hilfe der lock-Anweisung als kritischer Abschnitt gekennzeichnet werden. Daf\u00fcr muss eine Instanz eines Referenztyps als Sperrobjekt \u00fcbergeben werden. Bereiche, die dasselbe Sperrobjekt verwenden, werden niemals gleichzeitig durchlaufen.<\/p>\n<pre><code class=\"cs\">lock(m_SyncRoot)\r\n{\r\n  m_Sb.Append(...);\r\n  ...\r\n}<\/code><\/pre>\n<p>Der Einsatz von Sperren birgt immer ein Deadlock-Risiko. <a href=\"http:\/\/de.wikipedia.org\/wiki\/Deadlock\" rel=\"noopener\">Blockierungen<\/a> treten dann auf, wenn zwei Sperren in unterschiedlicher Reihenfolge benutzt werden. Solche Fehler sind schwer identifizierbar, da sie oft nur selten auftreten. Eine Ma\u00dfnahme zur Fehlerreduzierung ist eine \u00e4u\u00dferst sparsame Verwendung von Sperren. Au\u00dferdem sollten Sperren nur in einem lokalen Kontext benutzt werden.<\/p>\n<p>Sperren sind immer mit einem gewissen Overhead verbunden. Auch aus diesem Grund sollten Sperren nur dann verwendet werden, wenn es tats\u00e4chlich notwendig ist. Das folgende Beispiel zeigt eine sinnvolle Konstruktion bei der nur dann der kritische Bereich betreten wird, wenn das gew\u00fcnschte Objekt noch nicht angelegt ist. Zu beachten ist die doppelte \u00dcberpr\u00fcfung, da der Test nur im kritischen Bereich ein zuverl\u00e4ssiges Ergebnis liefert.<\/p>\n<pre><code class=\"cs\">if(m_ThreadSafeObject==null)\r\n{\r\n  lock(m_SyncRoot)\r\n  {\r\n    if(m_ThreadSafeObject==null)\r\n      m_ThreadSafeObject=new ThreadSafeObject()\r\n  }\r\n}<\/code><\/pre>\n<p>Das gezeigte Beispiel hat letztendlich nur den Effekt, dass das Objekt immer nur von einem Thread angelegt wird. Ohne die Sperre k\u00f6nnten mehrere Threads gleichzeitig ein Objekt erzeugen und der Member-Variablen zuweisen.<\/p>\n<h2>Spezielle Ma\u00dfnahmen<\/h2>\n<p>Das .NET Framework beinhaltet eine interessante Klasse zur Synchronisation von Threads, die gleichzeitige Lesezugriffe erlaubt. Schreibzugriffe hingegen erfolgen immer exklusiv. Die Klasse ReaderWriterLock aus dem Namensraum System.Threading sorgt so f\u00fcr eine h\u00f6here Abarbeitungsgeschwindigkeit, insbesondere dann, wenn Lesezugriffe gegen\u00fcber Schreibzugriffen \u00fcberwiegen.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Die Verwendung mehrerer Abarbeitungspfade (Threads) innerhalb eines Prozesses erfordert diverse Ma\u00dfnahmen zur Thread-Synchronisation, um Wettlaufsituationen auf gemeinsam genutzte Ressourcen zu unterbinden. In den meisten F\u00e4llen handelt es sich dabei um die Ressource Speicher.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[28],"tags":[25,19,20],"class_list":["post-347","post","type-post","status-publish","format-standard","hentry","category-multi-threading","tag-cs","tag-basics","tag-multi-threading"],"_links":{"self":[{"href":"https:\/\/www.steffen-liersch.de\/content\/de\/wp-json\/wp\/v2\/posts\/347","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.steffen-liersch.de\/content\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.steffen-liersch.de\/content\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.steffen-liersch.de\/content\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.steffen-liersch.de\/content\/de\/wp-json\/wp\/v2\/comments?post=347"}],"version-history":[{"count":8,"href":"https:\/\/www.steffen-liersch.de\/content\/de\/wp-json\/wp\/v2\/posts\/347\/revisions"}],"predecessor-version":[{"id":652,"href":"https:\/\/www.steffen-liersch.de\/content\/de\/wp-json\/wp\/v2\/posts\/347\/revisions\/652"}],"wp:attachment":[{"href":"https:\/\/www.steffen-liersch.de\/content\/de\/wp-json\/wp\/v2\/media?parent=347"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.steffen-liersch.de\/content\/de\/wp-json\/wp\/v2\/categories?post=347"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.steffen-liersch.de\/content\/de\/wp-json\/wp\/v2\/tags?post=347"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}