J'apprends une programmation simultanée en Java et j'écris une simulation pour le jeu de la vie. P>
Voici ce que je pense: p>
Maintenant, il y aura de la conflit aux frontières communes des segments. Si un fil écrit l'état d'une cellule à bordure avant que son voisin ait lu la valeur précédente, le calcul du voisin va être faux. p>
Quelles sont mes options? p>
Ma question est là, y a-t-il une autre façon de faire face à la conflit dans les cellules frontalières Mise à jour: Jusqu'à présent, le Une double solution tampon de Peter est la plus propre. Mais j'ai une question. Étant donné que les deux tableaux sont des données partagées et que nous n'utilisons aucune synchronisation (accès synchronisé ou variable volatile), ne créera-t-il pas de problème de visibilité forte>? Les processeurs multiples pourraient-elles mettre en cache des valeurs de matrice et mettre à jour seulement une partie de la matrice avec chaque itération? Ensuite, les threads obtiendront des valeurs obsolètes pour les cellules frontalières. Est-ce possible? Sinon, pourquoi. Si oui, comment puis-je le résoudre? Il semble Déclaration de deux tableaux volatils ne rendra pas leurs éléments individuels volatils . P>
5 Réponses :
Cela ne répond pas à votre question actuelle, mais ma recommandation serait votre première option ... avoir renvoyé les nouvelles valeurs plutôt que de les mettre à jour les threads de travailleur. Je prendrais une étape plus loin et que "Aggregator" combine les résultats des threads de travailleur dans un nouveau tableau d'état du tableau, puis jetez le premier. Mon raisonnement est qu'il améliorera la lisibilité globale de la logique, car il n'y aura que peu de "interactions mondiales", vous devez vous inquiéter. P>
Cela étant dit, je suis un peu biaisé parce que je préfère programmer de manière fonctionnelle sauf quand il y a une raison forte de ne pas. P>
Je voudrais essayer l'approche suivante: p>
Stockage requis pour un NXM CODE> TILE est
2 * (N + M - 1) CODE>, de manière générale des tuiles plus grandes (8x8 ou plus) nécessitent une mémoire moindre de manière proportionnelle pour la mise en cache valeurs. P>
Je suggère d'avoir 2 matrices d'int [] []. Appelons-les a et B. A contenir les valeurs de toutes les "ticks" impairs et B contiendront les tiques numérotées. P>
Initialiser A à quel que soit votre état initial ressemble. Ensuite, laissez vos discussions pour calculer l'état suivant de chaque cellule et placer les résultats dans la cellule correspondante en B. Une fois que tous vos threads sont terminés, vous avez votre nouvel état dans B. Maintenant, utilisez B pour calculer l'état suivant de chaque cellule et stocker les résultats dans A. À une heure donnée, un tableau sera en lecture seule et l'autre. écrire seulement, donc il n'y aura jamais de contention. P>
Avantages: P>
Inconvénients: P>
Ça semble bon. Mais j'ai une question sur la visibilité des données partagées. Voir la mise à jour.
Je viens de sotter sur java.util.concurrent.exchanger
Pour répondre à votre mise à jour sur le problème de la mise en cache avec double tampon, ce n'est pas un problème. Les CPU ont un cache cohérent et ils savent que les données ont été modifiées dans un autre cache de la CPU. P>
D'accord. Mais la visibilité est toujours une question due au modèle de mémoire Java. Lorsque le lien dans la mise à jour montre, déclarant que les références de matrices volatile et écrasent les références s'occuperont de cela. Cela signifie également que les processeurs ne peuvent pas mettre en cache les valeurs (ou jeter une fois que les références volatiles sont modifiées).
Bien lire ce lien, vous n'avez besoin que de la référence de la matrice pour être volatile, et non les données de la matrice. Vous pouvez simplement avoir un frontbuffer et une référence de retombeur, et de les échanger chaque itération. De cette façon, le contenu des tampons peut toujours passer par le cache de la CPU, les articles ne sont pas volatils, vous permettez donc d'utiliser une bonne utilisation des registres de la CPU, et vous n'avez aucune question de travail sur les anciennes données.
En réalité, l'utilisation d'une référence de matrice volatile pourrait vous ralentir en regardant l'adresse de la mémoire de la mémoire chaque utilisation, au lieu de le garder dans un registre de la CPU. Au début de chaque itération, vous pouvez copier les références volatiles en références temporaires non volatile, car vous ne les modifierez de toute façon pas pendant une itération.
quelque chose à considérer consiste à utiliser atomicint au lieu d'int
Avantage? Cela ne sera-t-il pas trop synchronisé?
Pourquoi avez-vous besoin d'utiliser INT, ne serait-il pas plus logique et efficace de stocker à l'aide de booléens?
Je ne. Dans mon code actuel, j'utilise Enum [] [].