2013-07-13 10 views
6

ich einen gleichzeitigen TCP-Server mir schreibe, die mehrere Verbindungen mit dem ‚Thread pro Verbindung‘ Ansatz (unter Verwendung eines Thread-Pool) zu behandeln hat. Mein Zweifel besteht darin, welcher der optimale Weg für jeden Thread ist, um einen anderen Dateideskriptor zu erhalten.Aufruf accept() von mehreren Threads

fand ich, dass die nächsten zwei Methoden, die empfohlen werden, sind:

  1. A Hauptthread dass accepts() alle eingehenden Verbindungen und speichert ihre Deskriptoren auf einer Datenstruktur (z.B .: a queue). Dann kann jeder Thread ein fd aus der Warteschlange bekommen.
  2. Accept() ist direkt von jedem Thread aufgerufen. (Empfohlen in Unix Network Programming V1)

Probleme ich jedem von ihnen finden:

  1. Die statische Datenstruktur, die alle fd Vorräte müssen gesperrt (mutex_lock), bevor ein Thread lesen von ihm, also in dem Fall, dass eine beträchtliche Anzahl von Threads in genau den gleichen Moment lesen möchte Ich weiß nicht, wie viel Zeit vergehen würde, bis alle von ihnen ihr Ziel erreichen würden.
  2. ich gelesen habe, dass das Thundering Herd Problem gleichzeitige accept() Anrufe im Zusammenhang wurde völlig bisher noch nicht auf Linux gelöst, vielleicht würde ich eine künstliche Lösung es schaffen müssen, die die Anwendung machen zumindest würde am Ende als langsam, wie mit dem Ansatz 1.

Quellen:

(Einige Links über Ansatz sprechen 2: does-the-thundering-herd-problem-exist-on-linux-anymore - und ein Artikel, den ich gefunden abo ut es (veraltet): linux-scalability/reports/accept.html

Und eine Antwort, so dass empfiehlt Ansatz 1: can-i-call-accept-for-one-socket-from-several-threads-simultaneously


Ich bin in der Sache wirklich interessiert, so dass ich eine Meinung darüber schätzen :)

Antwort

3

Wie in der StackOverflow answer erwähnt, die Sie verbunden haben, ist ein einzelner Thread, der accept() aufruft, wahrscheinlich der Weg zu gehen. Sie erwähnen Bedenken bezüglich des Sperrens, aber heutzutage finden Sie lockfreie Warteschlangenimplementierungen, die in Boost.Lockfree, Intel TBB und anderswo verfügbar sind. Sie können eine dieser Optionen verwenden, wenn Sie möchten, aber Sie können einfach eine Bedingungsvariable verwenden, um Ihre Worker-Threads in den Ruhezustand zu versetzen und eine davon zu aktivieren, wenn eine neue Verbindung hergestellt wird.

+0

Danke für die Idee der Zustandsvariablen, ich denke, dass es den Ansatz ziemlich effizient machen kann. Jedenfalls würde ich gerne wissen, ob der zweite Ansatz machbar ist oder nicht (nur um einige meiner Zweifel zu zerstreuen). (p.s.: Im Moment werde ich Ihre Antwort nicht akzeptieren, weil ich die Meinung anderer Leute bekommen möchte :)) – Str1101

+0

Der zweite Ansatz sollte für jede Warteschlangenimplementierung, die Sie für dieses Szenario schreiben, unbedingt gelten. Wenn Sie kein condvar verwenden, das intern zur Warteschlange gehört, werden die Thread-Clients auf ständige Abfragen reduziert, um zu sehen, ob Daten dort sind, wo sie wirklich schlafen wollen, bis etwas zu tun ist, dh wenn nichts in der Warteschlange ist lesen. – Duck

Verwandte Themen