7
votes

Suspendre Pthreads sans utiliser de condition

Je veux suspendre Pthreads mais apparemment, il n'y a pas de cette fonction de ce type que pthread_suspend. J'ai lu quelque part sur la suspension de Pthreads en utilisant des mutiles et des conditions et l'utiliser comme suit:

#include <pthread.h>

class PThread {
public:
pthread_t myPthread;
pthread_mutex_t m_SuspendMutex;
pthread_cond_t m_ResumeCond;

void start() {
pthread_create(&myPthread, NULL, threadRun, (void*)this );
}

Thread() { }

void suspendMe() {
pthread_cond_wait(&m_ResumeCond,&m_SuspendMutex);
}

void resume() {
pthread_cond_signal(&m_ResumeCond);
}
};


0 commentaires

6 Réponses :


5
votes

Si un fil n'attendait pas une condition ou une autre, comment pouvez-vous "signaler" cela pour reprendre. Il ne peut pas simplement arrêter d'exécuter quelque chose du tout, puis recommencer comme par magie, alors il attend une condition.

Elaborer, dans Pthreads, la façon de reprendre un thread est en fait pour utiliser des variables de condition. Il n'y a pas d'API disponible pour suspendre / reprendre un fil de toute autre manière. En attente sur pthread_cond_wait est bon marché, il bloque jusqu'à ce que la condition soit signalée, n'utilise pas (beaucoup?) CPU. Vous utilisez la condition pour signaler le fil pour se réveiller et que le mutex est nécessaire pour protéger l'accès à la variable de condition et le code dans le fil lors du réveil.


5 commentaires

"Comment pourriez-vous" signaler "ça pour reprendre?" C'est possible dans d'autres API! Par exemple, RENMETHREAD Dans l'API Windows fonctionne en acceptant un identifiant de thread entier. Il y a aussi un Suspendthread . Ensemble, vous pouvez facilement vous réveiller ou suspendre les threads de travailleur (du fil principal) dans une threadpool à mesure que le travail devient disponible ou fini.


Il existe un beau paragraphe ici qui décrit cette même chose.


@bobobobo Avez-vous lu la documentation pour ces fonctions? Ils ne sont pas pour la synchronisation de fil, mais pour les débuggeurs. pthreads est une bibliothèque fournissant la fonctionnalité de filetage, y compris la synchronisation. Ce n'est pas une bibliothèque de mise en œuvre de debuggleters, et il n'a donc pas d'équivalent des fonctions conçues pour une utilisation dans les débuggeurs


De la DOCS: "Cette fonction est principalement conçue pour être utilisée par debuggers. Il n'est pas destiné à être utilisé pour la synchronisation de fil. Appeler la suspension sur un fil qui possède un objet de synchronisation, telle qu'une section mutex ou critique, peut entraîner une impasse. Si le fil d'appel tente d'obtenir un objet de synchronisation appartenant à un thread en suspension. Pour éviter cette situation, un thread dans une application qui n'est pas un débogueur ne doit pas signaler à l'autre thread de se suspendre. Le fil cible doit être conçu pour surveiller cette signaler et répondre de manière appropriée. "


En fait oui, je viens de faire hier et j'ai réalisé que je me suis trompé. J'ai décidé de rester silencieux à ce sujet, mais vous l'avez dirigé, ce qui est bon.



9
votes

Votre code n'est pas correct - le pthread_cond_wait () code> nécessite que le mutex soit déjà verrouillé lorsque vous l'appelez:

class PThread {
    public:

    pthread_t myPthread;
    bool suspended;
    pthread_mutex_t m_SuspendMutex;
    pthread_cond_t m_ResumeCond;

    void start() {
        suspended = false;
        pthread_create(&myPthread, NULL, threadRun, (void*)this );
    }

    Thread() { }

    void suspendMe() {
        pthread_mutex_lock(&m_SuspendMutex);
        suspended = true;
        do {
            pthread_cond_wait(&m_ResumeCond, &m_SuspendMutex);
        } while (suspended);
        pthread_mutex_unlock(&m_SuspendMutex);
    }

    void resume() {
        /* The shared state 'suspended' must be updated with the mutex held. */
        pthread_mutex_lock(&m_SuspendMutex);
        suspended = false;
        pthread_cond_signal(&m_ResumeCond);
        pthread_mutex_unlock(&m_SuspendMutex);
    }
};


4 commentaires

De plus, vous devez vérifier votre condition après le réveil car le système peut réveille votre enfil avec la condition Faux! Par exemple, le système peut avoir réveillé 10 threads et l'un d'entre eux déjà terminé le travail.


@Zan lynx: aye, posix est assez clair sur ce point: "" Books parasites des fonctions Pthread_Cond_Timedwait () ou Pthread_Cond_Wait () peut se produire. " (Bien que je pense que la mise en œuvre de Linux ne fait pas de réveil. ).


Donc pthread_cond_wait est comme un dogchaain vraiment lâche. Votre Pitbull pourrait aller et commencer à mordre les voisins à une minute.


Non, c'est plus comme la cloche sur le comptoir dans un magasin. Si vous sonnez-le, le commerçant viendra certainement au comptoir et demandera ce que vous voulez, mais si vous ne siez pas, ils pourraient de toute façon.



2
votes

Une condition est toujours associée à un mutex. Habituellement, un thread va dormir car il attend qu'un changement d'état indique qu'il a du travail à faire; Vous avez besoin du mutex pour protéger l'accès à cet état et la condition de signaler le changement.

Réveillez-vous un fil sans le dire pourquoi vous avez réveillé que c'est un peu étrange à faire, il n'ya donc aucune façon particulière de le faire; La seule façon de le faire est d'utiliser le mécanisme normal, mais sans état partagé.

Si, pour une raison quelconque, vous souhaitez suspendre et reprendre le thread d'un autre fil, de manière indépendante de lui donner du travail à faire, vous pourrez peut-être utiliser pthread_kill pour l'envoyer SIGSTOP < / code> et sigcont signaux; Je n'ai jamais essayé de faire quoi que ce soit comme ça, alors je n'ai aucune idée de savoir si elle est soutenue ou non.


0 commentaires

0
votes

Les mutiles sont utilisés pour assurer l'accès exclusif, où les variables de condition sont utilisées pour synchroniser les threads en fonction des événements.

Nous avons besoin de mutexs pour vous assurer que les variables de condition ne finissent pas dans une attente infinie. Une chose à retenir est une opération mutex de verrouillage et de déverrouillage est garantie d'être atomique, mais les variables de condition ne doivent pas être. I.E Le thread peut être programmé pendant que la variable de variable d'attente est à mi-chemin.

Considérez l'affaire suivante avec Mutex pour la variable de condition.

fil 1


1) effectuer une certaine opération
2) Attendez la variable de condition
3) continue l'opération

Fil 2


1) effectuer une certaine opération
2) signaler la variable de condition
3) Continuer l'opération

ici dans le fil 1, l'étape 2 n'est pas garantie d'être atomique. Si le fil 1 est poussé hors de l'état d'exécution par planificateur avant de terminer l'étape1. Maintenant, le thread 2 commence à exécuter et signale la variable de condition. Lorsque le thread 1 reprend l'exécution, il finira les instructions de niveau bas restantes et commence à attendre. Le fil 1 finit dans une attente infinie, car le signal de variable de condition s'est produit même avant l'attente.

Donc, la bonne façon d'utiliser est (je crois que le code mentionné dans la question ne fait pas l'attente)

Fil 1: -


1) fonctionne jusqu'au point où une certaine condition doit se produire (telle que "Count" doit atteindre une valeur spécifiée)
2) verrouillage mutex associé
3) Appelez pthread_cond_wait () Pour effectuer une attente de blocage du signal de Thread1. (Notez qu'un appel à pthread_cond_wait () déverrouille automatiquement et atomique de la variable MuTex associée afin qu'elle puisse être utilisée par thread2)
4) Quand signalé, réveille-toi. MuTex est automatiquement et atomiquement verrouillé.
5) Déverrouiller explicitement mutex

fil2


1) faire du travail
2) verrouillage mutex associé
3) Modifiez la valeur de la variable globale que Thread1 attend.
4) Vérifier la valeur de la variable Global Thread1. S'il remplit la condition souhaitée, Signal thread1.
5) Déverrouillez mutex. Continuer


0 commentaires

-1
votes

plus au point - qu'est-ce que tu essayes finalement de faire ?? - Je soupçonne que la réponse n'est pas "suspendre un fil". Il se peut que votre conception de programme ait un problème.


0 commentaires

0
votes

On dirait qu'il n'y ait aucune alternative Linux à la fonction Suspendthread Windows API. Il est impossible de mettre en pause le fil Linux sans injection de code dans cette procédure de thread.


1 commentaires

Suspendthread dans le code de mode utilisateur est toujours malodorant. Même la documentation indique "Cette fonction est principalement conçue pour être utilisée par les débuggeurs. Il n'est pas destiné à être utilisé pour la synchronisation de fil.", Qui devrait suffire à quiconque vouloir l'utiliser.