Inhaltsverzeichnis
Frageninhalt
Lösung
Heim Backend-Entwicklung Golang Eine einfache Go-Simulation – Probleme mit der Parallelität

Eine einfache Go-Simulation – Probleme mit der Parallelität

Feb 09, 2024 pm 02:10 PM
数据访问

Eine einfache Go-Simulation – Probleme mit der Parallelität

php-Editor Xinyi bietet Ihnen ein einfaches, aber interessantes Go-Simulationsspiel namens „Concurrency Problem“. Dieses Spiel thematisiert die gleichzeitige Programmierung und ermöglicht es den Spielern, den Charme der gleichzeitigen Programmierung in einer virtuellen Welt zu erleben. Im Spiel müssen die Spieler Code schreiben, um die gleichzeitige Ausführung mehrerer Aufgaben zu bewältigen und ihre gleichzeitigen Programmierfähigkeiten zu testen. Die Spieloberfläche ist prägnant und klar, die Bedienung ist einfach, für Anfänger geeignet und bietet den Spielern außerdem mehrere Schwierigkeits- und Herausforderungsmodi zur Auswahl. Egal, ob Sie Anfänger oder erfahrener Entwickler sind, in diesem Simulationsspiel können Sie den Spaß am gleichzeitigen Programmieren genießen.

Frageninhalt

Ich bin ein Student aus Polen und habe dieses Semester einen parallelen Programmierkurs begonnen (Go, Ada und in Zukunft einige theoretische und CSP-Sprachen). Um ehrlich zu sein, sieht Golang interessant aus, aber ich bin etwas verwirrt. Unterm Strich würde ich mich selbst als unterdurchschnittlichen Programmierer bezeichnen. Grundsätzlich besteht meine Aufgabe darin, eine Simulation zu erstellen, die ich wie folgt beschreiben werde:

  • Es gibt ein n*m-Raster

  • Reisende können zufällig generiert werden, bis zu k Reisende, jeder Reisende hat eine eindeutige ID (1, 2, 3 usw., bis zu k)

  • Wenn der Platz frei ist (ich bin sicher, dass der freie Platz 0 ist), kann sich der Reisende zu zufälligen Zeitpunkten im Raster nach oben, links, rechts oder unten bewegen

  • Verfügt außerdem über eine Kamera, die manchmal den aktuellen Zustand des Netzes sowie aktuelle Bewegungen ausdruckt (noch nicht implementiert)

  • Inoffiziell habe ich gehört, dass ich Kanäle verwenden sollte, was auch immer das bedeutet

Meine Idee ist es, eine Struktur mit der ID und den Koordinaten jedes Reisenden zu erstellen und seine ID an den Kanal zu senden, der die Bereitschaft zur Bewegung darstellt, und dann werde ich zufällig die Bewegungsrichtung auswählen.

Ich bin etwas verwirrt über Parallelität – nicht nur, ob und wo ich WGs und Mutexe verwenden soll, sondern auch, ob ich zum Beispiel func(){} gehe, ob die Schleife innerhalb oder außerhalb sein soll. Ich würde mich sehr über Tipps, Hilfe oder Korrekturen/Ideen zur Korrektur meines Codes freuen, da er derzeit, wie Sie vermutet haben, nicht richtig funktioniert (z. B. wenn die Kamera das Raster druckt, gibt es manchmal mehr als k Reisende, wo mehrere). Reisende teilen sich die gleiche Nummer und manchmal scheinen sie zu verschwinden). Ich hoffe, alle haben einen tollen Tag und ich würde mich wirklich über jede Hilfe freuen :)

package main;

import(
    "fmt"
    "os"
    "strconv"
    "math/rand"
    //"sync"
    "time"
)

type traveler struct{
    id int;
    x int;
    y int;
}

func main(){

    //command line
    n, err := strconv.Atoi(os.Args[1]);
    m, err := strconv.Atoi(os.Args[2]);
    k, err := strconv.Atoi(os.Args[3]);
    if err != nil{
        panic(err)
        return
    }

    //board
    var grid [][]int;
    grid = make([][]int, n)
    for i:=0; i<n; i++{
        grid[i] = make([]int, m)
    }

    //array of travelers, channel for moves and id
    travelers := make([]traveler, k)
    no_of_travelers := 0;
    move := make(chan int, k);
    id := 1;

    //var wg sync.WaitGroup

    go camera(grid);

    go func() {
        
        for i:=0; i<len(travelers); i++ {   
            if no_of_travelers<k{
                travelers[i] = spawnTraveler(&id,grid);
                no_of_travelers++;
            }
        }
    }()

    go func() {
        for{
            a:= rand.Intn(k);
            sendMoveTraveler(&travelers[a], move);
        }
    }()

    receiveMoveTraveler(travelers, move, grid);

}

func spawnTraveler(id *int, grid [][]int) traveler{
    x:=-1;
    y:=-1;
    for{
        x = rand.Intn(len(grid));
        y = rand.Intn(len(grid));
        if(grid[x][y]==0){
            break;
        }
    }
    t := traveler{id: *id, x: x, y:y};
    grid[x][y] = *id;
    *id++;
    return t;
}


func sendMoveTraveler(t *traveler, move chan int){
        move <- t.id
}

func receiveMoveTraveler(travelers []traveler, move chan int, grid [][]int){
    for{
        id := <- move
        for i:=0; i<len(travelers); i++{
            if travelers[i].id == id{
                direction := rand.Intn(4); //1-left 2-up 3-right 4-down
                switch direction {
                case 0:
                    if travelers[i].x>0 && grid[travelers[i].x-1][travelers[i].y] == 0{
                        grid[travelers[i].x-1][travelers[i].y] = grid[travelers[i].x][travelers[i].y];
                        grid[travelers[i].x][travelers[i].y] = 0;
                        travelers[i].x = travelers[i].x-1;
                        travelers[i].y = travelers[i].y;
                    }
                case 1:
                    if travelers[i].y>0 && grid[travelers[i].x][travelers[i].y-1] == 0{
                        grid[travelers[i].x][travelers[i].y-1] = grid[travelers[i].x][travelers[i].y];
                        grid[travelers[i].x][travelers[i].y] = 0;
                        travelers[i].x = travelers[i].x;
                        travelers[i].y = travelers[i].y-1;
                    }
                case 2:
                    if travelers[i].x<len(grid)-1 && grid[travelers[i].x+1][travelers[i].y] == 0{
                        grid[travelers[i].x+1][travelers[i].y] = grid[travelers[i].x][travelers[i].y];
                        grid[travelers[i].x][travelers[i].y] = 0;
                        travelers[i].x = travelers[i].x+1;
                        travelers[i].y = travelers[i].y;
                    }
                case 3:
                    if travelers[i].y<len(grid)-1 && grid[travelers[i].x][travelers[i].y+1] == 0{
                        grid[travelers[i].x][travelers[i].y+1] = grid[travelers[i].x][travelers[i].y];
                        grid[travelers[i].x][travelers[i].y] = 0;
                        travelers[i].x = travelers[i].x;
                        travelers[i].y = travelers[i].y+1;
                    }
                }
                //fmt.Println("Ściagnalem ruch", travelers[i].id);
            }
        }
    }
}

func camera(grid [][]int){
    for{
    for i:=0; i<len(grid); i++{
        for j:=0; j<len(grid); j++{
            if grid[i][j]!= 0{
                fmt.Printf("%02d ", grid[i][j]);
            } else{
                fmt.Printf("-- ");
            }
        }
        fmt.Println();
    }
    fmt.Println();
    time.Sleep(time.Second * 3);
}
}
Nach dem Login kopieren

Ich bin ein wenig überwältigt von all den Ideen – WGs, Mutexe, Atome usw.

Lösung

  • Wenn Sie Arbeiten gleichzeitig verarbeiten möchten (z. B. das Aufnehmen eines Kameraschnappschusses und das Bewegen des Reisenden können gleichzeitig erfolgen), sind Goroutinen leichte Threads.
  • Kanäle werden zum Übertragen von Daten zwischen Go-Routinen verwendet.
  • Mutex wird verwendet, um Goroutinen das Hinzufügen von Sperren für gemeinsam genutzte Daten für den exklusiven Datenzugriff zu ermöglichen, um Race Conditions zu vermeiden.

Davon abgesehen:

  • Kamera-Schnappschüsse in einer Goroutine auszuführen, während sich der Reisende in einer anderen Goroutine bewegt, sieht gut aus. Das Spawnen der Goroutine ist nicht notwendig, Sie müssen es nur einmal tun, damit Sie es in der Haupt-Goroutine ausführen können.
  • In Ihrem Fall bringen Kanäle keinen Nutzen. Sie haben eine Goroutine, die eine Nachricht generiert und diese über einen Kanal an eine andere Goroutine sendet, die die Bewegung ausführt. Sie können dies alles nacheinander in einer einzigen Goroutine erledigen und unnötige Komplexität vermeiden. Kanäle sind für verschiedene Anwendungsfälle nützlich, hier sind sie jedoch überflüssig.
  • Da Sie über zwei Goroutinen verfügen, die auf den gemeinsamen Speicher (das Raster) zugreifen, benötigen Sie einen Mutex, um Race Conditions zu vermeiden. Immer wenn einer dieser Befehle ausgeführt wird, muss er „gesperrt“ werden, seine Arbeit abschließen und dann „entsperrt“ werden. Eine andere Goroutine blockiert den Sperrschritt, bis die erste Goroutine, die die Sperre erworben hat, die Sperre aufhebt. Sie können es mithilfe von Lese-/Schreibsperren weiter optimieren (Lesesperren werden nur für die Kamera und Lese-/Schreibsperren für die mobile Coroutine benötigt)
  • Wenn Sie mehr Zufälligkeit wünschen, können Sie für jeden Reisenden eine Goroutine erstellen.

Das obige ist der detaillierte Inhalt vonEine einfache Go-Simulation – Probleme mit der Parallelität. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

R.E.P.O. Energiekristalle erklärten und was sie tun (gelber Kristall)
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Beste grafische Einstellungen
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. So reparieren Sie Audio, wenn Sie niemanden hören können
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Wie man alles in Myrise freischaltet
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Was bedeutet Dao in Java? Was bedeutet Dao in Java? Apr 21, 2024 am 02:08 AM

DAO (Data Access Object) in Java wird verwendet, um den Anwendungscode und die Persistenzschicht zu trennen. Zu seinen Vorteilen gehören: Trennung: Unabhängig von der Anwendungslogik, wodurch diese leicht geändert werden kann. Kapselung: Verstecken Sie Datenbankzugriffsdetails und vereinfachen Sie die Interaktion mit der Datenbank. Skalierbarkeit: Leicht erweiterbar, um neue Datenbanken oder Persistenztechnologien zu unterstützen. Mit DAOs können Anwendungen Methoden aufrufen, um Datenbankoperationen wie das Erstellen, Lesen, Aktualisieren und Löschen von Entitäten durchzuführen, ohne sich direkt mit Datenbankdetails zu befassen.

Mit einer einzelnen Karte läuft Llama 70B schneller als mit zwei Karten, Microsoft hat gerade FP6 in A100 integriert | Mit einer einzelnen Karte läuft Llama 70B schneller als mit zwei Karten, Microsoft hat gerade FP6 in A100 integriert | Apr 29, 2024 pm 04:55 PM

FP8 und die geringere Gleitkomma-Quantifizierungsgenauigkeit sind nicht länger das „Patent“ von H100! Lao Huang wollte, dass jeder INT8/INT4 nutzt, und das Microsoft DeepSpeed-Team begann, FP6 auf A100 ohne offizielle Unterstützung von NVIDIA auszuführen. Testergebnisse zeigen, dass die FP6-Quantisierung der neuen Methode TC-FPx auf A100 nahe an INT4 liegt oder gelegentlich schneller als diese ist und eine höhere Genauigkeit aufweist als letztere. Darüber hinaus gibt es eine durchgängige Unterstützung großer Modelle, die als Open-Source-Lösung bereitgestellt und in Deep-Learning-Inferenz-Frameworks wie DeepSpeed ​​integriert wurde. Dieses Ergebnis wirkt sich auch unmittelbar auf die Beschleunigung großer Modelle aus – in diesem Rahmen ist der Durchsatz bei Verwendung einer einzelnen Karte zum Ausführen von Llama 2,65-mal höher als der von Doppelkarten. eins

Wie entferne ich den Schreibschutz eines USB-Flash-Laufwerks? Mehrere einfache und effektive Methoden können Ihnen dabei helfen Wie entferne ich den Schreibschutz eines USB-Flash-Laufwerks? Mehrere einfache und effektive Methoden können Ihnen dabei helfen May 02, 2024 am 09:04 AM

U-Disk ist eines der am häufigsten verwendeten Speichergeräte in unserer täglichen Arbeit und in unserem Leben, aber manchmal stoßen wir auf Situationen, in denen die U-Disk schreibgeschützt ist und keine Daten schreiben kann. In diesem Artikel werden mehrere einfache und effektive Methoden vorgestellt, mit denen Sie den Schreibschutz des USB-Flash-Laufwerks schnell entfernen und die normale Verwendung des USB-Flash-Laufwerks wiederherstellen können. Werkzeugmaterialien: Systemversion: Windows1020H2, macOS BigSur11.2.3 Markenmodell: SanDisk UltraFlair USB3.0-Flash-Laufwerk, Kingston DataTraveler100G3USB3.0-Flash-Laufwerk Softwareversion: DiskGenius5.4.2.1239, ChipGenius4.19.1225 1. Überprüfen Sie den physischen Schreibschutzschalter von Das USB-Flash-Laufwerk ist bei einigen USB-Flash-Laufwerken mit konzipiert

Was macht eine MySQL-Datenbank? Was macht eine MySQL-Datenbank? Apr 22, 2024 pm 06:12 PM

MySQL ist ein relationales Datenbankverwaltungssystem, das die folgenden Hauptfunktionen bietet: Datenspeicherung und -verwaltung: Daten erstellen und organisieren und verschiedene Datentypen, Primärschlüssel, Fremdschlüssel und Indizes unterstützen. Datenabfrage und -abruf: Verwenden Sie die SQL-Sprache, um Daten abzufragen, zu filtern und abzurufen und Ausführungspläne zu optimieren, um die Effizienz zu verbessern. Datenaktualisierungen und -änderungen: Hinzufügen, Ändern oder Löschen von Daten über INSERT-, UPDATE- und DELETE-Befehle, Unterstützung von Transaktionen zur Gewährleistung der Konsistenz und Rollback-Mechanismen zum Rückgängigmachen von Änderungen. Datenbankverwaltung: Erstellen und ändern Sie Datenbanken und Tabellen, sichern und wiederherstellen Sie Daten und stellen Sie Benutzerverwaltung und Berechtigungskontrolle bereit.

Wozu dient die API-Schnittstelle? Wozu dient die API-Schnittstelle? Apr 23, 2024 pm 01:51 PM

Eine API-Schnittstelle ist eine Spezifikation für die Interaktion zwischen Softwarekomponenten und dient der Umsetzung der Kommunikation und des Datenaustauschs zwischen verschiedenen Anwendungen oder Systemen. Die API-Schnittstelle fungiert als „Übersetzer“ und wandelt die Anweisungen des Entwicklers in Computersprache um, damit die Anwendungen zusammenarbeiten können. Zu den Vorteilen gehören ein bequemer Datenaustausch, eine vereinfachte Entwicklung, eine verbesserte Leistung, eine erhöhte Sicherheit, eine verbesserte Produktivität und Interoperabilität.

Was bedeutet Schema in MySQL? Was bedeutet Schema in MySQL? May 01, 2024 pm 08:33 PM

Schema in MySQL ist eine logische Struktur, die zum Organisieren und Verwalten von Datenbankobjekten (z. B. Tabellen, Ansichten) verwendet wird, um Datenkonsistenz und Datenzugriffskontrolle sicherzustellen und das Datenbankdesign zu vereinfachen. Zu den Funktionen von Schema gehören: 1. Datenorganisation; 2. Datenkonsistenz; 4. Datenbankdesign;

Verwendung der Serviceschicht in Java Verwendung der Serviceschicht in Java May 07, 2024 am 04:24 AM

Die Serviceschicht in Java ist für die Geschäftslogik und Geschäftsregeln zur Ausführung von Anwendungen verantwortlich, einschließlich der Verarbeitung von Geschäftsregeln, der Datenkapselung, der Zentralisierung der Geschäftslogik und der Verbesserung der Testbarkeit. In Java ist die Service-Schicht normalerweise als unabhängiges Modul konzipiert, interagiert mit der Controller- und Repository-Schicht und wird durch Abhängigkeitsinjektion implementiert, wobei Schritte wie das Erstellen einer Schnittstelle, das Einfügen von Abhängigkeiten und das Aufrufen von Service-Methoden ausgeführt werden. Zu den Best Practices gehören die Vereinfachung, die Verwendung von Schnittstellen, die Vermeidung direkter Datenmanipulationen, die Behandlung von Ausnahmen und die Verwendung der Abhängigkeitsinjektion.

Was sind die Anwendungsszenarien von Java Servlet? Was sind die Anwendungsszenarien von Java Servlet? Apr 17, 2024 am 08:21 AM

JavaServlet kann verwendet werden für: 1. Dynamische Inhaltsgenerierung; 3. Formularverarbeitung; 6. Sitzungsverwaltung; Beispiel: Erstellen Sie ein FormSubmitServlet, um die Formularübermittlung zu verarbeiten, indem Sie Name und E-Mail als Parameter übernehmen und an success.jsp umleiten.

See all articles