Je prépare le SCJP et la multithreading a été ma zone la plus shakieuse, principalement parce que je ne sais pas comment regarder du code multithreading et la promener. Jusqu'à présent, mon approche a été d'écrire en anglais ce qui pourrait se produire dans chaque fil et tester quelques cas avec des threads se croisant de manière aléatoire, ce qui est une approche vraiment frappante et fastidieuse. Je voudrais donc voir comment un professionnel irait à ce sujet. Seriez-vous prêt à lire le code ci-dessous (c'est la dernière question qui me donne des problèmes) et écrivez-vous ce qui se passe à travers votre tête (Stuff--------contre-Code uniquement, s'il vous plaît :) Lorsque vous travaillez les sorties possibles? Les choix qui viennent avec la question sont à la fin. Ce que je cherche n'est pas la solution, ce que j'ai, mais comment l'on arrive à la solution efficacement à l'examen.
et oui, je sais que cette question n'a pas de réponse précise, etc., etc. acceptée Le vote va à la réponse plus claire et la plus facile à imiter, d'accord :) p>
merci à tout le monde! p>
Question: laquelle de ces réponses sont des sorties possibles? P>
public class Threads1 {
int x = 0;
class Runner implements Runnable {
public void run() {
int current = 0;
for (int i = 0; i < 4; i++) {
current = x;
System.out.print(current + ", ");
x = current + 2;
}
}
}
public static void main(String[] args) {
new Threads1().go();
}
public void go() {
Runnable r1 = new Runner();
new Thread(r1).start();
new Thread(r1).start();
}
}
3 Réponses :
Mon approche des problèmes multi-threads consiste à rompre le code que le fil s'exécutera puis de déterminer le nombre de threads exécutera ce code et si l'accès à toutes les variables que d'autres threads pouvaient potentiellement utiliser. p>
Dans l'exemple, il y a 3 threads. Le Le fil code> principal code> va mourir après son retour de Les 2 autres threads vont accéder à la méthode Concernant ce que ces chiffres seront ne seront pas vraiment possibles car l'instance Comme mentionné ci-dessous par SB, l'option B, même s'il a 8 sorties, il n'est pas possible. Essayez de proposer une séquence de fil pour créer cette sortie. P> Appels de thread code> Nouveau threads1 (). Go (); code>, crée R1 code> et Démarre 2 threads, nouveau thread ( R1) .Start (); code> et nouveau thread (R1) .start (); code>. Maintenant que nous savons combien de threads nous pouvons suivre ce qu'ils vont faire. P>
Go () code>. p>
exécution () code> de l'objet code> objet code>, r1 code>. Maintenant, ce que nous savons aussi, c'est que chaque thread exécutera exécuter () code>. Permet de regarder ce que exécuter () code> fait. Il a une boucle pour code> qui imprime la sortie chaque fois qu'elle exécute la boucle. Par conséquent, l'appel à exécuté () code> imprimera 4 code> fois. Donc, 2 threads Chaque thread imprimera 4 code> fois. Par conséquent, la sortie ne peut avoir plus que 8 code>. P>
coureur code> sera la même pour chaque thread la variable x code> peut changer en fonction de l'autre Fil qui appelle également exécuté () code>. Par conséquent, tout ce dont vous avez besoin pour déterminer est que la séquence de chiffres est-elle possible? La réponse à cette question est «oui» pour A et C. Cela est dû au fait que vous n'avez aucune idée lorsque chaque thread sera préempté par l'autre et, depuis lors, lors de la boucle, une copie locale est faite, vous pourriez obtenir des commandes très uniques. P>
Oh wow. C'est un bon appel. Ma faute. Je vais corriger ça. Superbe capture.
La réponse pourrait être A, B, ou même C en fonction de la priorité Chaque thread a et que chaque instruction est exécutée. Ma meilleure hypothèse serait de répondre à une seule réponse qui affiche certains numéros répétés entrelacés, ce qui signifie que les deux threads sont exécutés en parallèle. Mais l'un des 3 premiers pourrait être justifié.
@Yanick - Non, je pensais qu'au début aussi mais B n'est pas possible. Vous ne pouvez pas avoir 6 numéros de plus en plus, puis 2 augmenter, car cela signifierait que 1 thread a écrit au moins 5 fois.
@ Linuxuser27, oui, j'ai essayé de modifier mon commentaire, mais je ne pouvais pas. B n'est pas valide, car lorsque 2 est écho du deuxième fil, le nombre suivant doit être supérieur ou égal à 12 du premier fil
@Yanick - C'est un exemple classique que même après des années de travail multi-filetés, vous pouvez toujours regarder la sortie "potentiel" et faire une erreur. Nous sommes en bonne compagnie que je suppose :)
@ Linuxuser27, Eh bien, il s'agit d'une queue classique d'un qui fait plus d'une chose à la fois et de ne pas accroître l'attention sur la question :) l'erreur est humaine. Si je faisais cet essai, j'aurais très probablement revu la question et la corrigera.
a et c fort> (en supposant que la question est laquelle de ces réponses sont des sorties possibles? em>) La partie difficile, bien sûr, n'est pas quand vous trouvez une solution possible. Mais plutôt, il est préférable de croire à celles que vous pensez être Jusqu'à présent, mon approche a été d'écrire en anglais ce qui pourrait se passer dans chaque thread ... p>
blockQuote> Vous devez déterminer quel fil imprimé chaque numéro. Vous trouverez ci-dessous le format de succion le plus efficace et le plus efficace que je puisse penser que et faciliter la croix / effacer / effacer / écrire au fur et à mesure que vous travaillez grâce à des possibilités. Réaliser: p> Une fois que vous avez trouvé une réponse possible Essayez d'abord l'approche la plus simple, par ex. Supposez T1 pour chaque numéro jusqu'à ce que vous n'ayez pas atteint un nombre qui ne pouvait pas être T1, alors vous remplissez T2, et ainsi de suite .. Espérons que vous arrivez à la fin sans contradiction (ni contradiction faciles à résoudre). Une fois que vous avez trouvé une combinaison possible, passez à autre chose. P>
li>
N'hésitez pas à passer à Éliminer em> les éventuels éventuels rapidement afin que vous puissiez vous concentrer sur les probablement impossibles. P>
li>
ul> Voici la dernière modification de ma feuille de travail / feuille de calcul (annexé avec mes annotations mentales): p> Remarque: p> http://download.oracle.com/javase/tutorial/essential/ Concurrence / Atomic.html P> Les actions atomiques ne peuvent pas être entrelées, elles peuvent donc être utilisées sans crainte d'interférences de fil. P>
blockQuote> p>
@Bertf pouvons-nous penser comme si ceci: peu importe l'exécution des threads, il doit y avoir la plupart des numéros imprimés, de sorte que d et e ne peuvent pas être produits par cet exemple, puis pour utiliser vos pensées pour A, B et C?
On dirait droit à moi @xelian - votre approche éliminerait rapidement D et E.
Cette question est beaucoup plus trompeuse qu'il n'y paraît - je l'aime, plus j'y pense. J'ai commencé ma réponse à parler de la façon dont je regarde les programmes de fil - j'analysez les points de synchronisation et les appels d'E / S. Mais cela n'en a aucun sauf pour l'imprimeur qui n'a pas de synchronisation interne. Nous sommes donc laissés au timing aléatoire (voir conditions de course ). Ceci combiné sans moyen garantie de synchroniser les valeurs de Cependant, si nous examinons les réponses, nous pouvons voir que certaines des réponses ne peuvent pas se produire. Par exemple, comme @ Linuxuser27 a signalé, chaque thread imprime 4 chiffres uniquement qui supprime les réponses aura plus de numéros imprimés. Un autre exemple de réponse inappropriée serait si l'une des réponses avait une valeur supérieure à 14 car le premier fil peut aller 0,2,4,6 et le 2ème pourrait le prendre à 8,10,12,14 mais pas plus élevé. p>
Étant donné que chacun des threads doit imprimer un numéro 4 fois et les chiffres imprimés par chaque thread em> doit être d'au moins 2+ le nombre précédent imprimé, certains des motifs ne peuvent pas être générés. Je ne donnerai pas ma réponse, mais n'est pas "tout ce qui précède" et ce n'est pas un, B et c. P> x code> entre les threads signifie qu'il sera aléatoire. P>
Chacun des chiffres doit être d'au moins 2+ le nombre précédent qu'ils ont imprimé code> Je pensais aussi, et j'étais tort :(
Si T2 avance plus que T1, T2's's's's's's's's's's actuel CODE> sera plus grand que celui du courant code> de T1, de sorte que lorsque T1 reprend le processeur de T2, X assumera le courant de T1 < / Code>, et que le courant code> inférieur code> sera imprimé après le plus haut. Donc, la sortie peut toujours descendre.
J'ai édité ma réponse. Ce que je voulais dire, c'est que le numéro de T1 monte toujours d'au moins 2 à partir de ce que T1 est également imprimé le numéro de T2.
Alors, quelle est la réponse Anita? J'aimerais voir votre réponse avant de vous donner ma façon de penser au problème.
La visualisation est la clé, faites votre propre technique de diagramme, suffisamment pour montrer ce qui se passe simultanément et quelles ressources sont partagées entre chaque fil.
Je n'ai pas donné la réponse parce que ça serait trop facile :) Sérieusement, une fois que je connais la réponse, je peux expliquer pourquoi c'est juste, mais il incitent à savoir ce qu'il est en premier lieu de faire et de faire 't faire encore.
La vraie réponse à cette question est que c'est horrible, horrible codage multithread et quiconque produisant du code comme celui-ci dans un environnement de production devrait non seulement être immédiatement licencié, mais en fait interdit de la programmation toujours.
@kyoryu imagine que vous avez un code hérité du refacteur pour refacteur, allez-vous simplement dire à votre patron »Nah, c'est un morceau de code laid de dieu, ne veux pas le réparer. Laissez-moi vérifier à la place! 11". Les exercices de filetage SCJP ne sont pas si mauvais, en fait, vous pouvez en apprendre à peu près.
@kyoryu a comme l'ancienne question mathématique sur les trains qui se déroulent à différentes vitesses et que vous devez comprendre quand ils se passent, le point de la question et le test sont pas b> pour montrer le code de production. Sa montrer que vous avez une forte compréhension des concepts et i> la capacité de les appliquer. Démérifier cette sortie est un bon moyen de démontrer cela.
Non, je corrigerais le code. Je suis à peu près sûr que la réponse est A, C ici et l'écart déverrouillé entre la lecture de la valeur actuelle de x et la modifier est la raison. Et oui, je comprends le point de l'exercice. Mais si les gens s'habituent à voir un code multithreading comme celui-ci, ma peur serait qu'elle penserait que c'est un moyen approprié de l'écrire et d'utiliser les «astuces» qu'ils ont trouvé dans le code comme celui-ci. Si Junior Devs cherche un mauvais code comme un exercice, je veux vraiment qu'ils soient conscients que c'est un mauvais code à l'avance.