Table des matières
Contenu de la question
Solution
Maison développement back-end Golang Une simple simulation Go - problèmes de concurrence

Une simple simulation Go - problèmes de concurrence

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

Une simple simulation Go - problèmes de concurrence

L'éditeur php Xinyi vous propose un jeu de simulation Go simple mais intéressant appelé "Concurrency Problem". Ce jeu prend pour thème la programmation simultanée, permettant aux joueurs de découvrir le charme de la programmation simultanée dans un monde virtuel. Dans le jeu, les joueurs doivent écrire du code pour gérer l'exécution simultanée de plusieurs tâches et tester leurs capacités de programmation simultanée. L'interface de jeu est concise et claire, et le fonctionnement est simple, adapté aux débutants pour débuter, et il offre également plusieurs modes de difficulté et de défi parmi lesquels les joueurs peuvent choisir. Que vous soyez débutant ou développeur expérimenté, vous pourrez profiter du plaisir de la programmation simultanée dans ce jeu de simulation.

Contenu de la question

Je suis un étudiant polonais et ce semestre j'ai commencé un cours de programmation concurrente (Go, Ada et quelques langages théoriques et CSP à l'avenir). Pour être honnête, Golang a l'air intéressant mais je suis un peu confus. L'essentiel est que, d'après mon expérience, je me qualifierais de programmeur inférieur à la moyenne. Fondamentalement, ma tâche est de créer une simulation, que je décrirai ainsi :

  • Il existe une grille n*m

  • Les voyageurs peuvent être générés aléatoirement, jusqu'à k voyageurs, chaque voyageur a un identifiant unique (1, 2, 3, etc., jusqu'à k)

  • A des moments aléatoires, si l'espace est libre (je suis sûr que l'espace libre est 0), le voyageur peut se déplacer vers le haut, la gauche, la droite ou le bas sur la grille

  • Dispose également d'une caméra qui imprime parfois l'état actuel du maillage ainsi que les mouvements récents (pas encore implémenté)

  • Officieusement, j'ai entendu dire que je devrais utiliser les chaînes, quoi que cela signifie

Mon idée est de créer une structure avec l'identifiant et les coordonnées de chaque voyageur et d'envoyer son identifiant au canal qui représente la volonté de bouger, puis je choisirai au hasard la direction du mouvement.

Je suis un peu confus au sujet de la concurrence - non seulement si et où dois-je utiliser wgs et mutex, mais aussi par exemple si j'utilise func(){} la boucle doit-elle être à l'intérieur ou à l'extérieur. Je serais très heureux d'apprécier tout conseil, aide ou correctif/idée pour corriger mon code car actuellement, comme vous l'avez deviné, il ne fonctionne pas correctement (par exemple lorsque l'appareil photo imprime la grille, il y a parfois plus de k voyageurs, où plusieurs les voyageurs partagent le même nombre et parfois ils semblent disparaître). J'espère que tout le monde passe une bonne journée et j'apprécierais vraiment toute aide :)

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);
}
}
Copier après la connexion

Je suis un peu dépassé par toutes les idées - wgs, mutex, atomes, etc.

Solution

  • Si vous souhaitez traiter le travail simultanément (par exemple, prendre un instantané de l'appareil photo et déplacer le voyageur peuvent se produire en même temps), les goroutines sont des threads légers.
  • Les canaux sont utilisés pour transférer des données entre les routines Go.
  • Mutex est utilisé pour permettre aux goroutines d'ajouter des verrous sur les données partagées pour un accès exclusif aux données afin d'éviter les conditions de concurrence.

Cela étant dit :

  • Exécuter des instantanés de caméra dans une goroutine tout en laissant le voyageur se déplacer dans une autre goroutine semble bien. Générer la Goroutine n'est pas nécessaire, vous ne devez le faire qu'une seule fois, vous pouvez donc l'exécuter dans la Goroutine principale.
  • Dans votre cas, les chaînes n'apportent aucun avantage. Vous avez un Goroutine qui génère un message et l'envoie via un canal à un autre Goroutine qui effectuera le mouvement. Vous pouvez faire tout cela séquentiellement dans une seule goroutine et éviter toute complexité inutile. Les canaux sont utiles pour différents cas d’utilisation, mais ici ils sont redondants.
  • Puisque vous avez deux goroutines accédant à la mémoire partagée (la grille), vous avez besoin d'un mutex pour éviter les conditions de concurrence. Chaque fois que l'un de ces éléments s'exécute, il doit se "verrouiller", terminer son travail, puis se "déverrouiller". Un autre goroutine se bloquera à l'étape de verrouillage jusqu'à ce que le premier goroutine qui a acquis le verrou se déverrouille. Vous pouvez l'optimiser davantage à l'aide de verrous en lecture/écriture (les verrous en lecture ne sont nécessaires que pour la caméra et les verrous en lecture/écriture pour la coroutine mobile)
  • Si vous souhaitez plus d'aléatoire, vous pouvez créer une goroutine pour chaque voyageur.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
2 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Repo: Comment relancer ses coéquipiers
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: Comment obtenir des graines géantes
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Combien de temps faut-il pour battre Split Fiction?
3 Il y a quelques semaines By DDD

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Que signifie Dao en Java Que signifie Dao en Java Apr 21, 2024 am 02:08 AM

DAO (Data Access Object) en Java est utilisé pour séparer le code d'application et la couche de persistance. Ses avantages incluent : Séparation : Indépendante de la logique de l'application, ce qui facilite sa modification. Encapsulation : masquez les détails d'accès à la base de données et simplifiez l'interaction avec la base de données. Évolutivité : facilement extensible pour prendre en charge de nouvelles bases de données ou technologies de persistance. Avec les DAO, les applications peuvent appeler des méthodes pour effectuer des opérations de base de données telles que la création, la lecture, la mise à jour et la suppression d'entités sans traiter directement les détails de la base de données.

À quel grade appartient le i7-13620h ? À quel grade appartient le i7-13620h ? Apr 15, 2024 pm 04:30 PM

Je crois que vous avez vu que parmi les derniers produits annoncés par Mechanic, il y a le dernier modèle i7-13620h. Alors, ce que tout le monde veut savoir, c'est à quel grade appartient le i7-13620h ? Le i7-13620h est un processeur hautes performances, appartenant à la gamme milieu-haut de gamme. Il utilise la technologie de processus d'Intel, possède 6 P-Core et 8 E-Core, un total de 14 cœurs et 20 threads, avec une fréquence principale de 2,6 GHz, une fréquence de cœur maximale de 5,0 GHz et est équipé de 96 ensembles de processeurs EU. cœurs Xe affichage de base. Le i7-13620h dispose d'une grande capacité de cache, y compris un cache de niveau trois (L3Cache), qui peut fournir une vitesse d'accès aux données plus rapide et accélérer le traitement et le calcul des données du processeur. vous croire

Une seule carte exécute Llama 70B plus rapidement que deux cartes, Microsoft vient de mettre le FP6 dans l'Open source A100 | Une seule carte exécute Llama 70B plus rapidement que deux cartes, Microsoft vient de mettre le FP6 dans l'Open source A100 | Apr 29, 2024 pm 04:55 PM

Le FP8 et la précision de quantification inférieure en virgule flottante ne sont plus le « brevet » du H100 ! Lao Huang voulait que tout le monde utilise INT8/INT4, et l'équipe Microsoft DeepSpeed ​​​​a commencé à exécuter FP6 sur A100 sans le soutien officiel de NVIDIA. Les résultats des tests montrent que la quantification FP6 de la nouvelle méthode TC-FPx sur A100 est proche ou parfois plus rapide que celle de INT4, et a une précision supérieure à celle de cette dernière. En plus de cela, il existe également une prise en charge de bout en bout des grands modèles, qui ont été open source et intégrés dans des cadres d'inférence d'apprentissage profond tels que DeepSpeed. Ce résultat a également un effet immédiat sur l'accélération des grands modèles : dans ce cadre, en utilisant une seule carte pour exécuter Llama, le débit est 2,65 fois supérieur à celui des cartes doubles. un

Comment supprimer la protection en écriture d'une clé USB Plusieurs méthodes simples et efficaces peuvent vous y aider ? Comment supprimer la protection en écriture d'une clé USB Plusieurs méthodes simples et efficaces peuvent vous y aider ? May 02, 2024 am 09:04 AM

Le disque U est l'un des périphériques de stockage couramment utilisés dans notre travail et notre vie quotidienne, mais nous rencontrons parfois des situations dans lesquelles le disque U est protégé en écriture et ne peut pas écrire de données. Cet article présentera plusieurs méthodes simples et efficaces pour vous aider à supprimer rapidement la protection en écriture de la clé USB et à restaurer l'utilisation normale de la clé USB. Matériel d'outils : Version du système : Windows1020H2, macOS BigSur11.2.3 Modèle de marque : Clé USB 3.0 SanDisk UltraFlair, Clé USB Kingston DataTraveler100G3USB3.0 Version du logiciel : DiskGenius5.4.2.1239, ChipGenius4.19.1225 1. Vérifiez le commutateur physique de protection en écriture de la clé USB sur certaines clés USB Conçu avec

Que signifie le schéma dans MySQL Que signifie le schéma dans MySQL May 01, 2024 pm 08:33 PM

Le schéma dans MySQL est une structure logique utilisée pour organiser et gérer les objets de base de données (tels que les tables, les vues) afin de garantir la cohérence des données, le contrôle d'accès aux données et de simplifier la conception de la base de données. Les fonctions de Schema comprennent : 1. Organisation des données ; 2. Cohérence des données ; 3. Contrôle d'accès aux données ; 4. Conception de la base de données ;

A quoi sert l'interface API ? A quoi sert l'interface API ? Apr 23, 2024 pm 01:51 PM

Une interface API est une spécification d'interaction entre des composants logiciels et est utilisée pour mettre en œuvre la communication et l'échange de données entre différentes applications ou systèmes. L'interface API agit comme un « traducteur », convertissant les instructions du développeur en langage informatique afin que les applications puissent fonctionner ensemble. Ses avantages incluent un partage pratique des données, un développement simplifié, des performances améliorées, une sécurité renforcée, une productivité et une interopérabilité améliorées.

Comment résoudre le problème de l'impossibilité d'accéder au système serveur Comment résoudre le problème de l'impossibilité d'accéder au système serveur Apr 16, 2024 pm 12:54 PM

Les directives pour résoudre l'inaccessibilité du système du serveur comprennent : la vérification des problèmes matériels (alimentation, câbles, ventilateurs) ; la vérification des connexions réseau (adresse IP, paramètres de passerelle) ; la vérification des paramètres du BIOS (ordre de démarrage, date et heure) ; mode sans échec), outils de réparation du système) ; vérifier les logiciels de sécurité (désactiver le logiciel antivirus, le pare-feu) ; vérifier les problèmes d'application (désinstaller, ajuster les paramètres) ;

Que fait la base de données MySQL ? Que fait la base de données MySQL ? Apr 22, 2024 pm 06:12 PM

MySQL est un système de gestion de base de données relationnelle qui fournit les fonctions principales suivantes : Stockage et gestion des données : créer et organiser des données, prenant en charge divers types de données, clés primaires, clés étrangères et index. Requête et récupération de données : utilisez le langage SQL pour interroger, filtrer et récupérer des données, et optimiser les plans d'exécution pour améliorer l'efficacité. Mises à jour et modifications des données : ajoutez, modifiez ou supprimez des données via les commandes INSERT, UPDATE, DELETE, prenant en charge les transactions pour garantir la cohérence et les mécanismes de restauration pour annuler les modifications. Gestion de bases de données : créez et modifiez des bases de données et des tables, sauvegardez et restaurez des données, et assurez la gestion des utilisateurs et le contrôle des autorisations.

See all articles