Hatte ich am 22. keine Frage in dem von mir kompilierten Programm? Jetzt habe ich dieses Problem im Grunde gelöst
Antworter: bluesmile979 (lacht) ( ) Reputation: 100 22.01.2003 21:08:00 Ergebnis: 0
Lassen Sie mich Ihnen meine Meinung sagen, ich denke, das größte Problem ist das Multithreading . Nach dem Lesen Ihres Codes scheint es, dass es nur zwei Zeilen gibt. Im Beispiel müsste es mehr Threads geben, wenn mehrere Threads um Zeitscheiben konkurrieren, ist die Wahrscheinlichkeit einer Unterbrechung natürlich viel höher. Selbst wenn Sie eine Schleife hinzufügen, ist diese aufgrund der Rechengeschwindigkeit der Maschine immer noch nicht so offensichtlich wie die Konkurrenz zwischen mehreren Threads. Ich weiß nicht, was Sie denken.
Antwort: xm4014(forrest) ( ) Reputation: 100 22.01.2003 22:07:00 Punktzahl: 0
an bluesmile979 (lacht)
Ich habe auch darüber nachgedacht, ob es daran liegt von Es wird durch zu wenige Threads verursacht, aber ich habe beide Parameter in der Think in Java-Routine auf 1 gesetzt, um es auszuführen, und am Ende ist es dasselbe wie das Programm, das ich geschrieben habe, mit nur zwei Threads, und das Ergebnis ist immer noch nicht synchron. Wie ist das zu erklären? Schließlich ist es zufällig und kommt selten vor. Es gibt nicht synchronisierte Vorkommnisse, aber wenn die Häufigkeit gering ist, ist es nicht leicht zu erkennen.
Meine übliche Methode besteht darin, zuerst die Endlosschleife zu starten, ohne dass während der Schleife eine Ausgabe erforderlich ist. Ich füge nur eine Stoppbedingung hinzu, wie zum Beispiel:
if (counter1 != counter2)
{
System .out.PRintln(counter1 + " ," + counter2)
System.exit(0);
}
Der Rest ist warten, normalerweise ist das Ergebnis in einem Dutzend Sekunden oder sogar ein paar Sekunden verfügbar Sekunden können Sie feststellen, dass die Zählung Hunderttausende oder Millionen erreicht hat.
Wenn 5 Threads gleichzeitig geöffnet sind und ich eine Minute warte, betrachte ich es als synchronisiert.
Meine Methode ist vielleicht nicht wissenschaftlich, aber die Wirkung ist ziemlich gut.
Antwort: xm4014(forrest) ( ) Reputation: 100 2003-01-23 11:44:00 Punktzahl: 0
Können Sie mir beim Debuggen helfen? Warum erhalte ich nie Ergebnisse, wenn ich Ihrer Methode folge?
Kopieren Sie einfach den folgenden Code direkt. Der Programmname lautet Sharing2.java und die Version ist 1.4.1
class TwoCounter erweitert Thread {
private int count1 = 0, count2 = 0;
private boolean gestartet=false;
public void start(){
if (!started)
{
started=true;
super.start();
}
}
public void run() {
while (true) {
count1++;
count2++;
// System.out.println("Count1="+count1+",Count2="+ count2 );
versuchen Sie {
sleep(500);
} Catch (InterruptedException e){System.out.println("TwoCounter.run");}
}
}
public void synchTest() {
// Sharing2.incrementaccess();
if(count1 != count2)
{System.out.println(count1+","+count2);
System.exit(0);
}
}
}
class Watcher erweitert Thread {
private Sharing2 p;
public Watcher(Sharing2 p) {
this.p = p;
start();
}
public void run() {
while(true) {
p.s.synchTest();
try {
sleep(500);
} Catch (InterruptedException e){System.out.println("Watcher.run");}
}
}
}
öffentliche Klasse Sharing2 {
TwoCounter s;
private static int accessCount = 0;
public static void incrementAccess() {
// accessCount++;
// System.out.println("accessCount= " +accessCount);
}
public static void main(String[] args) {
Sharing2 aaa = new Sharing2();
aaa.s=new TwoCounter();
aaa . s.start();
new Watcher(aaa);
}
} ///:~
Darüber hinaus gibt es Ihrer Meinung nach kein Problem mit meinem Programm, Es ist Es gibt nur weniger Threads und es ist schwierig, eine Desynchronisation zu verursachen. Das ist nur möglich, wenn der Zähler auf eine große Zahl ansteigt, oder?
Antwort von: hey_you(Hey) ( ) Reputation: 100 2003-01-23 13:27:00 Ergebnis: 0
Das denke ich: Konflikt aufgrund mangelnder Synchronisierung eine Möglichkeit, und synchronisiert macht diese Möglichkeit zu 0. Nur weil Sie die Synchronisation nicht entdeckt haben, können Sie nicht beweisen, dass es nie zu einer Synchronisation kommen wird. Es ist nur eine Frage der Zeit. Die Thread-Planung des Systems wird von der Umgebung beeinflusst. Wenn auf Ihrem Computer viele Programme gleichzeitig ausgeführt werden, kann die Situation anders sein.
Antwort: xm4014(forrest) ( ) Ruf: 100 2003-01-23 15:56:00 Ergebnis: 0
Haha, ich habe die Tianfeichen-Methode (aufmerksam zuhören) verwendet, um das Programm auszuführen, und Es hat funktioniert. Der Code, den ich oben gepostet habe, lieferte tatsächlich Ergebnisse: Zähler1 = 217327, Zähler2 = 217356, was ziemlich unterschiedlich ist. Aber die Zeit ist keineswegs so einfach wie ein oder zwei Minuten. Es kann an der Differenz zwischen meiner Betriebsumgebung und seiner liegen Zeit.
Ich hoffe, dass andere Leute weitere Meinungen äußern können, dann werde ich den Beitrag annehmen.
Antwort: bluesmile979 (lacht) ( ) Ruf: 100 23.01.2003 16:38:00 Ergebnis: 0
Ich mache den Test und Sie können ein oder zwei Stunden durchhalten, davon bin ich überzeugt.
Ich denke, das Ergebnis des Problems sind nur zwei Punkte. Das eine ist meiner Meinung nach die Anzahl der Threads
Das andere ist, was setText Ihrer Meinung nach mehr verarbeiten und mehr Ressourcen beanspruchen wird.
Beide Situationen wirken sich auf die Wahrscheinlichkeit dieses Problems aus :) Lassen Sie es mich zusammenfassen, haha.
Antwort: linliangyi (Blue Mountain Coffee) ( ) Ruf: 100 2003-01-23 17:10:00 Ergebnis: 0
Schlaf (500) nimmt mehr Zeit in Anspruch als für (5000) Zeit, Daher ist die Wahrscheinlichkeit, dass der Thread im Ruhezustand umgeschaltet wird, viel höher als die Wahrscheinlichkeit, dass er im Ruhezustand unterbrochen wird! ! (Sie werden es wissen, wenn Sie sich mein Programm noch einmal ansehen)
Tatsächlich ändern sich die beiden Variablen von ungleich zu gleich, was bedeutet, dass sie nicht synchron sind! !
Übrigens, wenn Swing- und AWT-Steuerelemente in Threads wie setText ausgeführt werden, verursachen sie häufig viele Unfälle
Das Originalplakat kann verwandte Bücher lesen! !
Antworter: xm4014(forrest) ( ) Reputation: 100 2003-01-24 14:25:00 Punktzahl: 0
Ich fasse eure Meinungen zusammen:
Das erste, was ich tun muss Stellen Sie sicher, dass die Möglichkeit einer Desynchronisierung definitiv besteht, wenn Sie das Schlüsselwort synchronisiert nicht zum Definieren einer Synchronisierungsmethode oder eines Synchronisierungsblocks verwenden. Synchronisiert macht diese Möglichkeit jedoch zu 0.
In der Im ersten Fall besteht zwar die Möglichkeit einer Desynchronisation, ihre Wahrscheinlichkeit wird jedoch durch die folgenden Faktoren beeinflusst
1 Unter verschiedenen Betriebssystemen und Betriebsumgebungen kann die Desynchronisation unterschiedlich sein oder die Wartezeit kann länger oder kürzer sein
2. Die Anzahl der Threads im Programm ist schwer zu erkennen und Sie müssen möglicherweise lange warten.
3 Der Code selbst. Beispielsweise kann die Verwendung von GUI-bezogenen Methoden in der AWT-Klasse mehr Ressourcen beanspruchen und viele Unfälle verursachen, sodass die Wahrscheinlichkeit von Konflikten viel größer ist.
4 Threads werden vom Betriebssystem zufällig zugewiesen ist inhärente Unsicherheit. Diese Unsicherheit wird sich auch auf das Endergebnis auswirken.
Ich weiß nicht, ob es richtig ist.
Morgen offiziell abgeschlossen
Aber um ehrlich zu sein Ich verstehe nicht, warum die Endergebnisse, Zähler1 (217327) und Zähler2 (217356), laut meinem Programm so unterschiedlich sind, selbst wenn der Watcher-Thread in zwei Inkrementierungsanweisungen eingefügt wird Der Unterschied zwischen den beiden erkannten Zählern liegt höchstens bei 1. Ein so großer Unterschied kann nur darauf zurückzuführen sein, dass die Selbstinkrementierungsanweisung eines bestimmten Zählers viele Male ausgeführt wurde, ohne dass sie überhaupt ausgeführt wurde Zu beängstigend! Obwohl die Existenz anderer Threads die Ausführung des aktuellen Threads stört, wird er höchstens warten und dann ausgeführt Wenn es Ihnen nichts ausmacht, helfen Sie mir bitte, es zu erklären. Daher muss ich jetzt bis morgen warten
Aber wir können heute ein weiteres Problem mit der Synchronisierung lösen. Dies ist ein Beitrag, den ich im Forum gesehen habe. Gerade weil ich ihn nicht lösen kann, halte ich es für notwendig, noch einmal die Threads und die Synchronisierung zu studieren Die Frage lautet wie folgt:
Datei://Analysieren Sie dieses Programm und erklären Sie es, wobei Sie sich auf synchronisiert, warten () und benachrichtigen konzentrieren. Danke!
class ThreadA
{
public static void main(String[] args)
{
ThreadB b=new ThreadB();
b.start();
System .out.println("b is start....");
synchronized(b)//Was bedeutet das b in den Klammern und welche Rolle spielt es?
{
versuchen
{
System.out.println("Warten auf den Abschluss von b...");
b.wait();//Was bedeutet dieser Satz und wer sollte warten?
System.out .println ("Abgeschlossen. Jetzt zurück zum Hauptthread");
}catch (InterruptedException e){}
}
System.out.println("Total is :"+b.total);
}
}
class ThreadB erweitert Thread
{
int total;
public void run()
{
synchronized(this)
{
System.out.println("ThreadB is run..");
for (int i=0;i<100;i++ )
{
total +=i;
System .out .println("total is "+total);
}
notify();
}
}
}
Um dieses Programm zu analysieren, müssen Sie zuerst Verstehen Sie notify () und wait (). Warum wurden diese beiden Methoden beim Aufzeichnen von Threads vor einigen Tagen nicht aufgezeichnet, da diese beiden Methoden ursprünglich nicht zur Thread-Klasse gehören, sondern zur Objektbasisklasse der niedrigsten Ebene? Worte, nicht nur Es ist Thread. Jedes Objekt hat Benachrichtigungs- und Wartefunktionen. Weil sie zum Manipulieren von Sperren verwendet werden und jedes Objekt eine Sperre hat. Da Sperren grundlegend sind, ist die Methode zum Manipulieren von Sperren natürlich auch die grundlegendste Wenn Sie weiterlesen, lesen Sie am besten Teil 3 von Think in Java 14.3.1: Warten und Benachrichtigen, also wait() und notify.
Befolgen Sie die Erklärung in Think in Java: „wait() erlaubt“. Wir versetzen den Thread in einen „Ruhezustand“, während wir „aktiv“ darauf warten, dass sich die Bedingungen ändern. Und nur wenn sich notify() oder notifyAll() ändert, wird der Thread geweckt und überprüft, ob sich die Bedingungen geändert haben >
Lassen Sie uns diesen Satz erklären.
„wait()“ ermöglicht es uns, den Thread in den „Ruhezustand“ zu versetzen, das heißt, „wait“ blockiert auch den aktuellen Thread, das ist dasselbe wie „sleep“ oder suspendieren. Was ist der Unterschied zwischen schlafen und suspendieren?
Der Unterschied besteht darin, dass „(warten) gleichzeitig“ darauf wartet, dass sich die Bedingungen ändern. Dies ist sehr wichtig, da wir manchmal die Hilfe der Synchronisierung (synchronisiert) benötigen Wenn die Synchronisierung verwendet wird, muss das Objekt gesperrt sein, dh die Objektsperre muss erworben werden. Andere Threads, die die Objektsperre verwenden möchten, können nur warten, bis alle Programme in der Synchronisierungsmethode oder im Synchronisierungsblock ausgeführt wurden Synchronisationsmethode: In synchronisierten Blöcken können weder sleep() noch suspend() die Sperre des verwendeten Objekts aufheben.
Aber warten Sie, es kann die Synchronisationsmethode oder den Der Synchronisationsblock gibt die Objektsperre vorübergehend auf und gibt sie vorübergehend an andere Personen weiter, die die Objektsperre benötigen (hier sollte es der Programmblock oder der Thread sein), was bedeutet, dass während der Ausführung andere Synchronisationsmethoden im Thread-Objekt aufgerufen werden können von wait()! In anderen Situationen (Ruhezustand, Suspend) ist dies nicht möglich. Beachten Sie jedoch, was ich zuvor gesagt habe. Ich gebe die Objektsperre nur vorübergehend auf und verwende sie vorübergehend für andere Threads Warten Sie, bis dieses Objekt zurückgenommen wurde. Warten Sie einfach und geben Sie es mir zurück, nachdem es von jemand anderem verwendet wurde.
Okay, wie bekomme ich dann die Objektsperre zurück?
Die erste Methode besteht darin, die Leihzeit in wait() zu begrenzen, z. B. wait(1000), was bedeutet, dass ich nur leihe 1 Sekunde lang herausnehmen und nach einer Sekunde automatisch zurücknehmen
Die zweite Methode besteht darin, die Person, die es geliehen hat, zu bitten, mir mitzuteilen, dass er es aufgebraucht hat und es mir zurückgeben möchte Dieses Mal nehme ich es sofort zurück. Hey, was ist, wenn ich es für eine Stunde aufbereite und jemand anderes nur eine halbe Stunde braucht, um es zu beenden? , egal wie lange ich es einrichte.
Wie benachrichtigen mich also meiner Meinung nach jeder? ) oder notifyAll() ändert, wird der Thread geweckt.“ .
Daher können wir ein wait() und notify() in jede synchronisierte Methode oder jeden synchronisierten Block einfügen, unabhängig davon, ob die Thread-bezogene Verarbeitung in dieser Klasse vorbereitet ist . Und tatsächlich können wir wait() und notify() nur in einer synchronisierten Methode oder einem synchronisierten Block aufrufen
Zu diesem Zeitpunkt ist es für uns einfach, das obige Programm zu erklären.
synchronisiert(b){...} bedeutet, einen synchronisierten Block zu definieren und b als Ressourcensperre zu verwenden. b.wait(); bedeutet, die Sperre vorübergehend aufzuheben und den aktuellen Thread zu blockieren, damit andere Threads, die dieselbe Sperre verwenden, die Möglichkeit haben, die gleiche Sperre zu verwenden. Dieser Thread wird dies tun Verwenden Sie danach notify(), um den Thread darüber zu informieren, dass die Sperre aufgebraucht ist. Nachdem der Synchronisierungsblock, in dem sich notify() befindet, ausgeführt wurde, kann der Thread, in dem sich wait befindet, ausgeführt werden Weiter ausführen.