pthread Thread-Objekte setzen ihren Zustand zurück

8

Als ich kürzlich mit der Erweiterung pthreads gearbeitet habe, habe ich eine Anomalie entdeckt. Ich habe ein einfaches Objekt mit einem internen Zustand:

%Vor%

Jetzt habe ich eine Thread-Klasse erstellt, die etwas mit diesem Objekt macht:

%Vor%

In meiner Hauptfunktion habe ich ein Sum-Objekt erstellt, es in den Thread eingefügt und es gestartet:

%Vor%

Ich habe erwartet, dass das Ergebnis 50 ist, weil der Thread den Wert 10 mal um 5 erhöhen musste. Aber ich habe ein 0 !

Interessanter ist, dass es nicht die Synchronisation zurück in den Hauptthread ist, die fehlgeschlagen ist, aber der Thread scheint sogar seinen internen Zustand auf dem Weg zu vergessen: Die Ausgabe des Echos in der run() -Methode ist nicht die erwartete 5 10 15 20 25 30 35 40 45 50 aber 0 0 0 0 0 0 0 0 0 0 . Niemand behindert den Thread - warum behält er seinen Zustand nicht bei?

Randnotiz: Wenn ich den Thread nicht starte, sondern die run () - Methode direkt im Haupt-Thread ( $thread->run(); ) aufruft, ist das Ergebnis immer noch dasselbe. Aber wenn ich jetzt extends Thread in der Klassendeklaration entferne, funktioniert es perfekt und gibt die erwartete 5 10 15 20 25 30 35 40 45 50 zurück.

    
Francois Bourgeois 28.01.2013, 14:30
quelle

3 Antworten

17

Jedes Objekt, das nicht von einer Pthreads-Definition abstammt, wird serialisiert, wenn es als Mitglied eines von Pthreads abstammenden Objekts gesetzt wird.

Operationen wie + = und [] verwenden Zeiger intern, Serialisierung ist nicht kompatibel mit Zeigern für andere Objekte. Im Handbuch auf der Einführungsseite heißt es, dass jedes Objekt, das von mehreren Kontexten manipuliert werden soll, Stackable, Thread oder Worker wie

erweitern sollte %Vor%

Wenn Sum keine Zeiger verwendet, können Sie nach dem Join die Referenz aus dem Thread-Objekt abrufen.

Dies sind einfache Vorgänge, die Sie nicht synchronisieren müssen. Sie sollten nur dann synchronisieren, wenn Sie auf ein Objekt warten oder es benachrichtigen möchten.

Die mit Pthreads gebündelten Objekte sind für diese Umgebung sehr viel besser geeignet und werden niemals serialisiert.

Bitte lesen Sie das Intro im Handbuch und alle Beispiele in den Methoden, die Sie verwenden möchten, um genau herauszufinden, was was ist, dann können Sie fragen warum:)

Ich weiß, dass Benutzer von PHP es nicht gewohnt sind, Nachforschungen anzustellen, aber wir arbeiten hier an der Grenze, Sie werden feststellen, dass es richtige Wege gibt, Dinge auf unkorrekte Weise zu tun, die meisten davon sind in Beispielen dokumentiert und alles, was nicht sicher ist, wird mir auf SO entzogen und findet schließlich den Weg zur Dokumentation.

Ich bin mir nicht sicher, ob das Beispiel, das Sie angegeben haben, gerade Objekte getestet hat, aber der von Ihnen bereitgestellte Code nicht zwei Objekte sein muss und auch nicht zwei Objekte sein sollte, beachten Sie Folgendes:

%Vor%

Es kann für Sie nützlich sein, ein paar weitere Funktionen in Aktion mit einer Erklärung zu sehen, also hier ist ein ähnliches Beispiel wie bei Ihnen:

%Vor%

Dies kombiniert einige der fortgeschritteneren Funktionen in einigen einfachen Beispielen und wird kommentiert, um Ihnen zu helfen. Im Hinblick auf die Freigabe von Objekten ist es nicht falsch, ein Thread-Objekt zu übergeben, wenn es einige Funktionen und Daten enthält, die in anderen Threads oder Stackables benötigt werden. Sie sollten versuchen, so wenig Threads und Objekte wie möglich zu verwenden, um die Arbeit zu erledigen.

    
Joe Watkins 28.01.2013, 15:40
quelle
1

Ihr Problem besteht darin, dass Sie auf die Variable vom Hauptthread und vom MyThread-Thread zugreifen. Die CPU speichert die Variable im Cache und sie wird im Cache für MyThread aktualisiert, aber nicht im Cache für den Hauptthread, sodass Ihre beiden Threads die anderen Threadänderungen nie sehen. In Java / C usw. gibt es das Schlüsselwort volatile, aber ich weiß nicht, ob das in PHP existiert.

Ich denke, Sie sollten versuchen, die Methoden in Summe synchronisiert aufzurufen ( Ссылка )

Zum Beispiel statt:

%Vor%

Anruf:

%Vor%     
th3falc0n 28.01.2013 14:39
quelle
0

Ich dachte, ich mache auch etwas falsch. Wie bereits erwähnt [] und andere Operationen mit Zeigern wird nicht funktionieren. Dies ist die Problemumgehung:

%Vor%

Dies funktioniert, da wir die Operation [] für eine temporäre Funktionsvariable verwenden und sie als Klassenvariable festlegen.

Besseres Beispiel, warum ist es notwendig:

%Vor%

So können wir der Variablen in mehr als einer Funktion neue Elemente hinzufügen und hinzufügen. Das gleiche gilt für + = und andere Operatoren, aber Sie benötigen die temporäre Variable dafür.

Einfach zu erweitern Funktion dafür:

%Vor%

Eval könnte hier funktionieren, aber ich finde das viel sicherer.

    
Trouble 31.08.2014 23:43
quelle