Was bedeutet es, ein dynamisches Array threadsicher und gleichzeitig zu machen? Sagen Sie beispielsweise %code% .
Gibt es also etwas, das über %code% erledigt werden muss, um es threadsicher und gleichzeitig zu machen oder ist es threadsicher und gleichzeitig standardmäßig?
Die einzigen gleichzeitigen Operationen für ein einzelnes Objekt in der Standardbibliothek, die standardmäßig sicher sind, sind - Nur Zugriff auf %code% -Member Funktionen - Alle Zugriffe auf Synchronisationsprimitive (wie Mutex Lock und Unlock oder atomare Operationen) Alles andere muss extern synchronisiert werden. Insbesondere hat die Standardbibliothek noch keine threadsicheren Container (ab c ++ 14)
Die Antwort auf beide Beispiele ist also nein, beide erfordern eine Form der externen Synchronisation.
Sie können natürlich den Wert zweier verschiedener Elemente im Container ändern.
C ++ 11 sagt Folgendes über die Thread-Sicherheit von Containern in der Standardbibliothek:
23.2.2 Containerdatenrassen [container.requirements.dataraces]
Zum Zweck der Vermeidung von Datenrennen (17.6.5.9) müssen Implementierungen Betrachte die folgenden Funktionen als const: %code% , %code% , %code% , %code% , %code% , %code% , %code% , %code% , %code% , %code% , %code% , %code% und, außer in assoziativen oder ungeordnete assoziative Container, %code% .
Ungeachtet (17.6.5.9) sind Implementierungen erforderlich, um Daten zu vermeiden Rennen, wenn der Inhalt des enthaltenen Objekts in verschiedenen Elementen in der gleichen Reihenfolge, mit Ausnahme von %code% , werden geändert gleichzeitig.
Das Lesen von einem Container aus mehreren Threads ist also in Ordnung, und das Modifizieren von Elementen, die sich bereits im Container befinden, ist in Ordnung (solange sie verschiedene Elemente sind).
Daher ist keine der beiden spezifischeren Fragen für %code% threadsicher:
1) Zwei Threads, die in den Vektor eingefügt werden, modifizieren den Vektor selbst - keine existierenden separaten Elemente.
2) Das Löschen eines Threads und anderes Gehen, um auf dasselbe Element zuzugreifen, ist nicht sicher, da das Löschen eines Elements aus dem Vektor keine Operation ist, die threadsicher ist (oder "frei von Datenrennen" wie der Standard) setzt es).
Um diese Operationen sicher ausführen zu können, muss das Programm eine externe Synchronisation selbst vornehmen.
Ich bin Anfänger in Java und erstelle gerade ein Kartenspiel wie Gin Rommé für Android. Ich möchte wissen, was die beste Implementierung für die Erstellung der Handklasse ist? Wie kann man die von Deck.dealt () zurückgegebene Karte am besten speichern?
Außerdem würde ich mich freuen, wenn jemand einen Gin Rommé Open-Source-Link zur Verfügung stellen könnte.
Ich denke, eine gute Idee wäre, eine Schnittstelle zu verwenden (Liste, wenn Elemente geordnet sind, oder Setzen, wenn Elemente nicht geordnet sind. Sie können die gewünschte Implementierung verwenden, zum Beispiel:
%Vor%oder
%Vor%Speichern Sie sie in %code% .
Karten in einer Hand sind in einer bestimmten Reihenfolge, nicht in einem ungeordneten Haufen. Diese Reihenfolge wird in %code% über %code% beibehalten.
%code% gibt Ihnen auch die Möglichkeit, eine bestimmte Karte nach Index auszuwählen, was bei der Implementierung des Spiels hilfreich ist.
Beachten Sie, dass Sie diese Datenstruktur jederzeit problemlos ändern können, solange Sie Ihre %code% -Klasse ordnungsgemäß erstellen. Solange Sie dies bei jeder von Ihnen entworfenen Klasse berücksichtigen, können Sie sie jederzeit ändern, wenn Sie merken, dass Sie etwas anderes brauchen.
Nun, ein %code% ist schneller (soweit ich weiß), aber wenn du ein Kartenspiel machen willst, dann wirst du vielleicht die Karten sortieren wollen. Deshalb würde ich vorschlagen, eine Liste zu verwenden. Wenn Sie ein Anfänger sind, dann wäre vielleicht das Beste, ein %code% zu verwenden. Es ist einfach zu bedienen und zu verstehen. Zumindest würde ich das tun. Wenn Sie mehr erfahren möchten, empfehle ich, über die einzigartigen Eigenschaften jedes einzelnen zu lesen, damit Sie selbst entscheiden können. Und ja, wie Greuze schon sagte, sollten Sie eine Schnittstelle für mehr Flexibilität verwenden.
Erstens wird von der Verwendung von Vector in den neuesten Versionen von Java abgeraten, so dass Sie diese wahrscheinlich ignorieren können.
Zweitens, wie Sie wissen werden, wenn Sie das Javadoc auf diesen restlichen Klassen lesen, haben sie alle Vorteile oder Nachteile. Manche haben eine Bestellung, manche können doppelte Werte annehmen, manche nicht und so weiter. Daher denke ich, der beste Ansatz ist es, einen Pseudo-Code für Ihre Anwendung zu schreiben, der nicht auf einer bestimmten Klasse basiert (schreiben Sie einfach Dinge wie "Karte zu Hand hinzufügen", "Karte aus der Hand entfernen"). Sobald Sie etwas von diesem Pseudo-Code haben, werden Sie in der Lage sein, Ihre Anforderungen klarer zu sehen; Wollen Sie die Karten in einer bestimmten Reihenfolge in der Hand behalten? Willst du Karten mit einem Schlüssel aus der Hand holen?
Dann wird Ihre Wahl klarer sein.
Es ist sinnvoll, das Deck in einer Liste zu behalten, da es die Reihenfolge aufrechterhält. Ich verwende standardmäßig Lists.newArrayList (), um eine Liste zu erstellen. Listen ist ein Teil von Guava. Ich empfehle sehr, Guava zu verwenden und kennen zu lernen, da es viele nützliche Angebote hat.
Es wäre sinnvoll, die Hand in einer leicht sortierbaren Datenstruktur zu halten, um den Vergleich der Hände zu erleichtern. OTOH, IIRC, Gin Rummy Hände sind nicht allzu groß.
Wenn Sie die Nuancen zwischen den Sammlungsarten wirklich verstehen wollen, gehen Sie hier.
%code% ist technisch nicht angemessen, außer wenn das Spiel Bohnanza ist (was, ähm, ist einer der größte Kartenspiele aller Zeiten, aber ich lasse mich fertig machen).
%code% sagt unter anderem, dass eine Hand, die das Ass und den König der Vereine enthält, und eine andere Hand, die den König und das Kreuz enthält, grundsätzlich nicht dieselbe Hand sind. Das ist eine viel stärkere Abhängigkeit von der Ordnung als einfach "Nun, ich möchte mich an die Reihenfolge erinnern, in der der Benutzer seine Karten sehen möchte", was eine Eigenschaft ist, die Tonnen von Nicht-Listen-Sammlungen haben, wie %code% und Guavas %code% .
%code% impliziert auch, dass der Karte im Index N eine besondere Bedeutung beigemessen wird. Dies gilt für kein Kartenspiel, das ich kenne.
%code% ist im Allgemeinen nicht für Kartenspiele geeignet - nur für diejenigen, die ein einziges Kartenspiel mit völlig einzigartigen Karten verwenden.
Um Duplikate zu erlauben, aber trotzdem eine gruppenunabhängige Gleichheit zu haben, ist der zu verwendende Typ Guavas %code% . Zum Beispiel %code% oder %code% . Beachten Sie, dass die meisten Multiset-Implementierungen mehrere "gleiche" Karten darstellen, indem Sie nur die Karte und eine Zählung speichern. Wenn Sie über sie iterieren, müssen Duplikate einer Karte, die Sie auf der Hand haben, immer zusammen erscheinen. Wenn es wichtig ist, dass der Benutzer die Reihenfolge der Karten in seiner Hand frei steuern kann, benötigen Sie %code% .
Jetzt ist die Unterrichtszeit vorbei ... nun, seien wir ehrlich. % Co_de% aufzurufen, oder eine ganze Hand als Schlüssel in %code% zu verwenden, ist nicht wirklich was du jemals tun wirst ... also mach weiter und benutze %code% , du Mir geht es gut. : -)