2016-10-21 10 views
1

Ich habe ein einfaches c-Programm (auf Linux). Die Schritte im Programm sind wie folgt:Alternative zu schlafen, Semaphoren

  • Innerhalb einer while-Schleife ruft es eine Abfrage auf, die genau einen Datensatz zurückgibt. Es ist im Wesentlichen eine Ansicht, die nach einer Spalte mit dem Namen "processed" mit dem Wert "0" sucht und "limit 1" verwendet.

  • Ich lese die Datensätze in der Ergebnismenge und führe einige Berechnungen durch und lade die Ergebnisse zurück in die Datenbank. Ich habe auch die verarbeitete Spalte auf "1" gesetzt.

  • Wenn diese Abfrage keine Datensätze zurückgibt, beende ich die While-Schleife.

  • Sobald die while-Schleife beendet wird, wird das Programm beendet.

  • Sobald es ausgeführt wird, möchte ich nicht, dass das Programm beendet wird. Der Grund dafür ist, dass die Datenbank in den nächsten 30 Minuten möglicherweise mehr qualifizierende Datensätze erhält. Ich möchte, dass dieses Programm ein lang laufendes Programm ist, das nach neuen Datensätzen sucht und die while-Schleife erneut startet, um die Datensätze zu verarbeiten.

    Ich mache keine Multi Threading oder ausgefallene Sachen. Ich habe etwas googlen und Posts über Semaphore gefunden.

    Ist das der richtige Weg? Gibt es einfache Beispiele für Semaphore mit Erklärung?

    +2

    Semaphore sind für Multithreading-Synchronisation. Ich kann mir nicht vorstellen, dass sie hier nützlich wären. – Riley

    +1

    Dies ist ein Beispiel für das "Producer/Consumer Problem". Semaphore (und andere Synchronisationsgrundelemente) sind nur dann anwendbar, wenn Sie sowohl den Producer (den externen Prozess) als auch Ihren Consumer (Ihr Programm) ändern können, um diese zu nutzen. Sie werden Ihnen in einer Singlethread-Anwendung nicht helfen oder wenn der Hersteller keine systemweite IPC nutzen kann (oder kann). Die Verwendung von sleep ist akzeptabel, obwohl Sie einen Systemzeitgeber verwenden sollten, um den Kernel freizugeben. – Dai

    +0

    Ich bin mir nicht sicher, was Sie fragen. Sie möchten nicht, dass das Programm beendet wird. Beenden Sie das Programm nicht am Ende der Schleife. Ich denke, deine eigentliche Frage ist: "Wie kann ich mein Programm am besten warten lassen, bis es noch mehr Sachen zu verarbeiten gibt?" – Schwern

    Antwort

    1

    Zuerst hoffe ich, dass Sie eine Transaktion verwenden. Andernfalls kann es eine Wettlaufsituation zwischen 1 und 2 geben.

    Ich denke, Ihre Frage ist "Woher weiß Ihr Programm, wenn mehr Informationen in einer SQL-Tabelle verarbeitet werden?" Es gibt mehrere Möglichkeiten, dies zu tun.

    Die einfachste ist . Ihr Programm prüft nur gelegentlich, ob es Arbeit gibt. Wenn nicht, schläft es eine Weile. Wenn die Überprüfung billig ist oder Sie nicht sehr oft überprüfen müssen, ist die Abstimmung in Ordnung. Es ist ziemlich robust, es gibt keine Koordination zwischen dem Arbeiter und dem Lieferanten. Der Arbeiter sucht nur nach Arbeit.

    Eine andere Möglichkeit besteht darin, das Programm auf eine Art von I/O zu blockieren, wie auf das Sperren einer Datei zu warten. Darum geht es bei Semaphoren. Es geht so.

    1. Die Warteschlange ist leer.
    2. Der Produzent erhält eine exklusive Sperre für die Semaphor-Datei.
    3. Ihr Arbeiter versucht, die Semaphor-Datei zu sperren, sie blockiert.
    4. Der Produzent fügt der Warteschlange hinzu und gibt seine Sperre frei.
    5. Der Arbeiter entsperrt sofort.
      1. Überprüft die Warteschlange
      2. Funktioniert.

    ... aber das Zurücksetzen des Systems ist ein Problem. Der Produzent weiß nicht, wann die Warteschlange wieder leer ist, ohne zu pollen.Und dies erfordert, dass alles, was der SQL-Tabelle hinzugefügt wird, über diese Prozedur informiert ist und sich auf demselben Computer befindet. Selbst wenn es funktioniert, ist es sehr anfällig für Deadlocks und Race Conditions.

    Ein anderer Weg ist über Signale. Der Erzeugerprozess sendet ein Signal an den Arbeiterprozess, um zu sagen "Ich habe etwas Arbeit hinzugefügt". Wie oben erfordert dies eine Koordination zwischen den Dingen, die zu der SQL-Tabelle und den Arbeitern hinzugefügt werden.

    Eine bessere Lösung besteht darin, SQL nicht für eine Arbeitswarteschlange zu verwenden. Es ist von Natur aus etwas, was Sie abfragen müssen. Verwenden Sie stattdessen eine Named- oder eine Netzwerk-Pipe. Pipes fungieren automatisch als Warteschlange. Produzenten schreiben an das Rohr, wenn sie Arbeit hinzufügen. Der Arbeiter verbindet sich mit dem Rohr und liest daraus, um mehr Arbeit zu bekommen. Wenn es keine Arbeit gibt, blockiert es ruhig das Warten auf Arbeit. Die Pipe kann alle Informationen enthalten, die für die Arbeit erforderlich sind, oder sie kann nur einen Hinweis darauf enthalten, dass an einem anderen Ort gearbeitet wird (z. B. eine ID für eine Zeile).

    Schließlich, je nachdem, wie viel Verarbeitung durchgeführt werden muss, könnten Sie versuchen, alle diese Verarbeitung in einer gespeicherten Prozedur, ausgelöst durch eine Tabellenaktualisierung, durchzuführen.

    +0

    In diesem speziellen Beispiel müssen Sie keine Transaktionen durchführen, da es kein Multi-Thread-Verfahren und somit keine Race-Bedingungen gibt. –

    +0

    @AndreasLundgren Jedes Mal, wenn Sie SQL lesen, verarbeiten und dann aktualisieren, besteht die Gefahr einer Datenbeschädigung. Ein anderer Prozess könnte sich mit der SQL-Datenbank verbinden und mit den gleichen Zeilen arbeiten, die Sie bearbeiten. Es ist grundlegende SQL-Datenintegrität. Du vertraust nicht, dass du der einzige Prozess bist; vielleicht bist du jetzt, aber wer weiß, was später passiert? Sie verwenden eine Transaktion. – Schwern

    +0

    Danke euch allen. Ich muss über verschiedene hier beschriebene Strategien nachlesen. – KartDev