web-dev-qa-db-fra.com

Comportement de dispatch_get_global_queue

Le code suivant:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    for (int i=0; i<100000; i++) {
        NSLog(@"HIGH 1 %d", i);
    }
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
    for (int i=0; i<100000; i++) {
        NSLog(@"LOW %d", i);
    }
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    for (int i=0; i<100000; i++) {
        NSLog(@"HIGH 2 %d", i);
    }
});

résulte en un mélange de bûches haute 1, haute 2 et basse.

Comment se fait-il qu'il imprime simultanément les journaux high1 et high2. les blogs high1 et high2 ne sont-ils pas dans la même file d'attente? Donc, le bloc high1 ne devrait-il pas terminer avant de commencer à exécuter le bloc high2?

28
Ashish Awaghad

Cela dépend de la machine sur laquelle vous exécutez. Je soupçonne que vous exécutez cela sur votre Mac, car GCD créera automatiquement suffisamment de threads pour le système spécifique pour les travaux dans les files d'attente globales. Donc, vous avez probablement plus d'un cœur, donc GCD exécute vos tâches sur les deux cœurs.

Si vous créez votre file d'attente à l'aide de dispatch_queue_create, vous obtenez une file d'attente série, et vous êtes alors garanti FIFO comportement.

FWIW (bien que vous ne devriez pas vous fier à ce comportement), si vous exécutez cela sur l'iPhone, je soupçonne que vous verrez un comportement de file d'attente série, car votre iPhone est monocœur. Ne vous fiez pas à cela cependant, l'iPad 2 est multi-core je pense!

ÉDITER:

Documentation pour dispatch_get_global_queue: Renvoie une file d'attente globale simultanée bien connue d'un niveau de priorité donné.

22
joerick

Vous venez d'illustrer pourquoi vous ne devriez pas appeler des méthodes qui ne sont pas thread-safe dans dispatch_async. S'il y a suffisamment de cœurs de traitement pour exécuter plus de travaux, GCD ira de l'avant et empilera le travail dessus, que les travaux précédents dans une file d'attente donnée soient retournés ou non. Le même comportement peut être obtenu sous OS X 10.7 en créant vos propres files d'attente avec:

dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);

De toute évidence, NSLog() peut être appelée aussi souvent que vous le souhaitez sans vous soucier des erreurs d'accès ou similaires, mais si vous êtes préoccupé par la sécurité des threads ou l'ordre dans lequel vos travaux retournent, envisagez d'utiliser des groupes de répartition.

6
Chris Mowforth

dispatch_get_global_queue est une sorte de file d'attente de simultanéité. Comme vous spécifiez la même priorité pour high1 et high2, le résultat est un mélange de high1 et high2. Après cela, ce sera le résultat faible car il a une priorité inférieure.

0
scorpiozj