Es kann nur EINEN geben! 💻 Das Singleton-Pattern in C# / Java

แชร์
ฝัง
  • เผยแพร่เมื่อ 25 มิ.ย. 2024
  • Entdecke die Grundlagen und Feinheiten des Singleton-Patterns in unserer neuen Videoreihe über Softwarequalität und Design Patterns. In diesem Video zeigen wir, wie das Singleton-Pattern funktioniert, wann es eingesetzt wird und welche Best Practices es gibt. Egal, ob du ein Anfänger oder ein erfahrener Entwickler bist - dieses Video bietet wertvolle Einblicke für jeden. Bleib dran, denn in zukünftigen Videos gehen wir noch tiefer in die Materie ein!
    #BuilderPattern #SoftwareDesign #softwarearchitecture #UML #NestedBuilder #FacetedBuilder #Coding #Programming #DesignPatterns #Java #CSharp #SoftwareEngineering #beginners #oop #ObjektorientierteProgrammierung #objectorientedprogramming #cleancoding #C#
    ──────────────────────────────────────
    ► Folge uns
    Instagram: / memoryleekde
    TikTok: / memoryleekde
    Twitter: / memoryleekde
    LinkedIn: / memoryleekde
    ──────────────────────────────────────
    ► Studieren in Remagen
    🧑‍🎓 www.hs-koblenz.de/mathematik-...
    ──────────────────────────────────────
    ► Kapitel
    0:00 Intro
    1:01 Problemstellung
    3:31 UML
    4:43 Implemtation
    8:11 thread-safe
    9:36 Vor- & Nachteile
    ──────────────────────────────────────
    ► Kontakt
    kontakt@memoryleek.de

ความคิดเห็น • 21

  • @g2h5j3
    @g2h5j3 25 วันที่ผ่านมา +2

    Warum überprüft man jetzt bei 9:09 noch mal ob die Instanz null ist? So wie ich das jetzt verstanden habe kommt der Thread doch nicht in den Programmblock rein wenn ein anderer Thread schon dabei ist ein neues Objekt zu erstellen. Oder kann zwischen der ersten If-Abfrage und dem lock-Block ein anderer Thread die Zuweisung so schnell durchführen?

    • @MemoryLeekDE
      @MemoryLeekDE  25 วันที่ผ่านมา +4

      Danke für die Frage! Genauer werden wir in unserer Multithreading Videoreihe darauf eingehen, aber hier schonmal die Antwort:
      Zuerst führt ein Thread die erste Überprüfung if (instance == null) durch, um festzustellen, ob die Instanz bereits erstellt wurde. Wenn die Instanz null ist, versucht der Thread, die Sperre zu erwerben. In diesem Moment kann es jedoch passieren, dass der Thread unterbrochen wird und ein anderer Thread ebenfalls die erste Überprüfung durchführt. Da die Instanz immer noch null ist, wird der zweite Thread die Sperre erwerben und die Instanz erstellen. Wenn der erste Thread seine Ausführung fortsetzt und die Sperre erwirbt, würde er ohne die zweite Überprüfung ebenfalls versuchen, eine neue Instanz zu erstellen. Dies würde das Singleton-Prinzip verletzen, welches sicherstellen soll, dass nur eine einzige Instanz der Klasse existiert.
      Die doppelte Überprüfung dient also dazu, sicherzustellen, dass die Instanz nicht mehrfach erstellt wird. Sobald der erste Thread die Sperre erworben hat, überprüft er nochmals, ob die Instanz bereits von einem anderen Thread erstellt wurde. Wenn die Instanz inzwischen erstellt wurde, überspringt der erste Thread die Erstellung einer neuen Instanz und gibt die bereits existierende Instanz zurück. Dies garantiert, dass nur eine einzige Instanz der Klasse erstellt wird, auch in einer multithreaded Umgebung.

    • @g2h5j3
      @g2h5j3 25 วันที่ผ่านมา +1

      @@MemoryLeekDE Ah okay, danke mir war nicht bewusst das Threads so unterbrochen/pausiert werden können. Aber das werd ich ja dann bald hier sehen ;)

    • @EikeSchwass
      @EikeSchwass 22 วันที่ผ่านมา

      @@g2h5j3 Der erste Check ist vor allem eine Performanceoptimierung. Am Verhalten würde sich nichts grundsätzlich ändern, wenn man den ersten Check nicht hätte, aber das würde in Multithreading-Szenarien zu übermäßigem Locking führen, weil dann potenziell jeder Aufruf von GetInstance in einen Lock rennen kann.

    • @pinkeHelga
      @pinkeHelga 18 วันที่ผ่านมา

      @@g2h5j3 Ja, ein Lock wartet - bestenfalls mit einem Timeout, je nach System/Sprache - bis andere Threads ihren Lock wieder freigeben. Das ist der Sinn des Konstrukts.
      Multithreading beherrbergt Race Conditions. Mit einem Lock ist es auch nicht unbedingt getan. Schnell läuft man in einen Dead-Lock. Dann sperren sich 2 Threads gegenseitig, und nichts geht mehr. Es gibt viele Konzepte, wie man den Teufel mit dem Belzebub austreibt.
      Eines der besten Konzepte ist, einen dedizierten Prozeß/Thread für solche kritischen Aufgaben bereitzustellen, der bei Bedarf benachrichtigt wird.
      Btw.: Vom Singleton-Muster bin ich eh kein Freund. Es ist imgrunde nur eine neue Form von globaler Variablen und bringt damit ähnliche Probleme mit sich. Und in den meisten Umgebungen sind auch statische Klassenmethoden und Eigenschaften verfügbar, die quasi das selbe ermöglichen. Keine Notwendigkeit, eine Instanz zu erstellen.
      Und statische Klassen sind imgrunde auch nur wieder ein Mißbrauch als Namespace. Die meisten Sprachen bieten inzwischen das Konzept von Namespaces an.
      Besser man hat eine verantwortliche Kontrolleinheit, die eine Instanz erzeugt, und die wird dann herumgereicht.

  • @sadakazu_yoshikawa
    @sadakazu_yoshikawa 15 วันที่ผ่านมา +1

    Endlich mal jemand, der dinge wirklich gut verständlich erklärt und vorallem mit wirklich einfach zu verstehenden beispielen verdeutlicht wieso warum weshalb so und nicht anders.
    Danke für eure Videos :) die bringen mich gerade enorm nach vorne :D

  • @RonnieTreibholz
    @RonnieTreibholz 25 วันที่ผ่านมา +1

    Gut erklärt aufjedenfall! :D
    Wobei ich mir auch gleich wieder dachte, Ja … Parallelität war ein Fehler, macht alles nur komplexer :P
    Aber neja, benötigt man nun mal auch heutzutage :)
    Ich glaube, das Singleton war das erste Pattern, was wir damals programmieren mussten, damals noch in Java. War auf jeden Fall interessant zu sehen, wie C# das löst, bei Java war es glaube ich mit synchronized, ist aber schon 'ne weile her. Wenn ich mich recht entsinne, wurde damit eine Methode markiert als, "hey, hier darf nur ein Thread dran arbeiten."
    Interessant wäre es in C gewesen, weil ich denke … da hätte man seine eigenes "lockobject" schreiben müssen. Wobei sicher den Rahmen des Videos gesprengt hätte :D

  • @martapfahl940
    @martapfahl940 22 วันที่ผ่านมา +1

    Gutes Video! Weißt du zufällig ob die von Intel ja relativ neu eingeführten Performance Cores und Efficiency Cores konkret mit C# angesteuert werden können oder ob das immer automatisch passiert? Beispiel ich will Prozesse die stärkere Rechenpower benötigen auf die P-Cores schicken und Prozesse die schnell gehen auf die Efficiency Cores? Wenn ja weißt du wie das umgesetzt wird? Muss ja vermutlich mit dem Compiler abgestimmt sein. Ich persönlich hab nen Ryzen 5800X3D, da gibts das ja zB gar nicht.

    • @MemoryLeekDE
      @MemoryLeekDE  22 วันที่ผ่านมา +1

      Die kurze Antwort ist: Weiß ich nicht genau!
      Aber: Die Verwaltung von P-Cores und E-Cores erfolgt hauptsächlich durch das Betriebssystem und den Thread Director. In C# kannst du aber Prozessaffinität und Thread-Prioritäten einstellen und so Threads auf bestimmte Kerne setzen z.B. process.ProcessorAffinity = (IntPtr)0x000F setzt die Affinität auf die ersten 4 Kerne.
      Die Priorität von Threads geht über Thread thread = new Thread(MethodName);
      thread.Priority = ThreadPriority.Highest;
      Wie sich das exakt auf die P- und E-Cores auswirkt, weiß ich nicht.
      That said ... ich glaube, dass die Optimierungsregeln des Betriebssystems schon ziemlich stark sind. Ich verstehe aber den Wunsch eingreifen zu wollen. Wenn jemand mehr weiß, freue ich mich auch dazu zu lernen.

    • @martapfahl940
      @martapfahl940 21 วันที่ผ่านมา

      @@MemoryLeekDE Top danke dir für die ausführliche Antwort :)

  • @Krauttrooper
    @Krauttrooper 16 วันที่ผ่านมา +1

    Der Audiomanager ist ein gutes Beispiel dafür was ein ungeeignetes Beispiel ist. Eine property mit privaten setter und dann eine ne Methode die einen Wert über den setter setzt. Das ist Java kein c# .

    • @MemoryLeekDE
      @MemoryLeekDE  16 วันที่ผ่านมา

      Danke für dein Feedback! Du hast recht, dass die Methode ChangeVolume, die eine Property mit einem privaten Setter verwendet, eher an Java erinnert. In C# wäre es idiomatischer, entweder direkt eine Methode zu verwenden, die die Property setzt, oder die Property direkt zugänglich zu machen, wenn keine spezielle Logik erforderlich ist. Das Singleton-Pattern selbst ist korrekt implementiert, aber deine Anmerkung zur Property-Nutzung hilft, den Code klarer und idiomatischer zu gestalten. Vielen Dank dafür!

  • @fairphoneuser9009
    @fairphoneuser9009 25 วันที่ผ่านมา

    Bei lock war ich erst verwirrt wegen dem fehlenden Strichpunkt, bis ich verstanden habe, dass das ein Konstrukt ist und keine Funktion.
    Singletons sollte man jedenfalls vorsichtig einsetzen, weil jedes Singleton-Objekt eigentlich eine globale Variable ist.

    • @MemoryLeekDE
      @MemoryLeekDE  25 วันที่ผ่านมา +1

      Vielen Dank für deinen Kommentar! Und ja, der lock-Befehl in C# hat kein Semikolon, da es sich um ein Kontrollkonstrukt und keine Funktion handelt. Was deine Anmerkung zu Singletons betrifft, hast du absolut recht. Singletons sollten mit Vorsicht verwendet werden. Sie können die Wartbarkeit und Testbarkeit des Codes beeinträchtigen. Es ist immer wichtig, die Notwendigkeit eines Singletons zu überdenken und sicherzustellen, dass es die beste Lösung für das jeweilige Problem darstellt. Viele (auch ich) streichen auch Singletons irgendwann komplett aus ihrem Programmierinventar...

    • @squadwuschel
      @squadwuschel 25 วันที่ผ่านมา

      @@MemoryLeekDE oder man injected es per Singleton, dann geht es auch wieder :-)

  • @EikeSchwass
    @EikeSchwass 22 วันที่ผ่านมา

    Gilt ja mitlerweile als Anti-Pattern, vor allem da man über IoC-Container mit Singleton-Lifetime alle Vorteile aber eigentlich keine der Nachteile bekommt und somit die bevorzuziehende Variante ist.
    Singletons machen (Unit-)Tests wirklich absolut fürchterlich zu schreiben und sollten, alleine deshalb, so gut es geht vermieden werden.

    • @MemoryLeekDE
      @MemoryLeekDE  22 วันที่ผ่านมา

      Absolut, in einer Reihe über Design Patterns, kann ich sie dennoch nicht auslassen :-/

  • @hrtmtbrng5968
    @hrtmtbrng5968 17 วันที่ผ่านมา

    Die ganze Konstruktion kommt mir relativ gestelzt vor. Was Du eigentlich willst, ist eine ganz banale globale Variable. Damit dein Code besser testbar ist, baust Du eine Klasse drumherum. Damit die Klasse gemockt werden kann, baust Du eine Instanz. Damit die Instanz singulär ist, baust Du einen eigenen Konstruktor. Damit der Thread safe ist, baust Du einen Mutex drum herum. Und dann wünschst Du Dir, dass Anwender von den Singleton dieses nicht direkt verwenden. Also baust Du noch ein Interface drumherum. Viel Wirbel um eine simple globale Variable.

    • @MemoryLeekDE
      @MemoryLeekDE  17 วันที่ผ่านมา +1

      Ein globales Objekt trifft es besser, aber ansonsten ist das eine schöne Zusammenfassung.