web-dev-qa-db-fra.com

Est-ce que Thread.yield () fait quelque chose si nous avons suffisamment de processeurs pour desservir tous les threads?

Si nous sommes dans une situation avec deux threads en cours d'exécution sur une machine avec deux processeurs et que nous appelons Thread.yield() au sein de l'un de ces threads, est-ce que cela ne se passera pas (le planificateur ignorera essentiellement la demande) parce que nous avons suffisamment de processeurs pour desservir les threads en cours d'exécution?

39
Dave

Chaque fois qu'un thread appelle la méthode Thread.yield(), il indique au planificateur de thread qu'il est prêt à suspendre son exécution. Le planificateur de threads est libre d'ignorer cet indice.

Si un thread exécute la méthode yield, le planificateur de thread vérifie s'il existe un thread exécutable (en attente d'exécution) avec une priorité identique ou élevée à ce thread. Si le processeur trouve un thread avec une priorité supérieure ou identique, il basculera vers un nouveau thread. Sinon, le thread actuel continue de s'exécuter.

Puisque, dans votre exemple, vous avez suffisamment de processeurs pour desservir tous les threads (ils sont en cours d'exécution, sans attendre dans un état exécutable); Thread.yield() ne fera rien et vos threads continueront leur exécution.

Une note sur Windows, de Microsoft DOTNet:

Cette méthode équivaut à utiliser l'invocation de plate-forme pour appeler la fonction native Win32 SwitchToThread .

Le rendement est limité au processeur qui exécute le thread appelant. Le système d'exploitation ne basculera pas l'exécution vers un autre processeur, même si ce processeur est inactif ou exécute un thread de priorité inférieure. S'il n'y a pas d'autres threads prêts à être exécutés sur le processeur actuel, le système d'exploitation ne produit pas d'exécution

Il peut donc y avoir des mises en garde dans certaines situations.

27
Guillaume F.

Thread.yield() est obsolète. À moins que votre programme ne s'exécute sur une plate-forme qui implémente multitâche coopératif ou sur une machine virtuelle Java qui utilise toujours fils verts, alors il ne sert à rien de l'appeler.

La bibliothèque standard Javadoc pour Thread.yield() dit effectivement que yield() n'a rien à faire du tout.

13
Solomon Slow

J'ai toujours pensé que Thread::yield doit être remplacé par Thread::onSpinWait (puisque Java 9) - c'est juste une forme de rendement "plus faible", jusqu'à ce que j'aie vu une utilisation de both dans StampedLock :

    else if ((LockSupport.nextSecondarySeed() & OVERFLOW_YIELD_RATE) == 0)
        Thread.yield();
    else
        Thread.onSpinWait();
    return 0L;

Je ne pense donc pas que ce soit obsolète. En interne dans les sources jdk, il a de nombreux usages, même le relativement nouveau ForkJoinPool a des usages de Thread::yield.

En pratique, je n'ai utilisé que Thread::onSpinWait à l'intérieur des spins occupés - parce que alt du moins d'après le nom de celui-ci - il est très clair quand l'utiliser; d'autre part, le rendement n'est pas - donc je ne peux pas dire avec certitude quand et comment l'utiliser.

Juste mon 0,02 $.

7
Eugene