Programmation concurrente CSI 2520 Hiver 2007 Programmation concurrente

  • Slides: 23
Download presentation
Programmation concurrente CSI 2520, Hiver 2007

Programmation concurrente CSI 2520, Hiver 2007

Programmation concurrente • La programmation est distribuée lorsque les processus ne partagent pas la

Programmation concurrente • La programmation est distribuée lorsque les processus ne partagent pas la mémoire • Sinon la programmation est dite parallèle CSI 2520, Hiver 2007

Processus • Un processus ou tâche est une instance d'un programme ou d' une

Processus • Un processus ou tâche est une instance d'un programme ou d' une partie d' un programme pouvant être exécuté de façon autonome • Un langage de programmation concurrente doit permettre: – la création de processus: des processus concurrents peuvent être créés à partir de n' importe quel langage en utilisant de mécanismes explicites de programmation concurrente – la synchronisation de leurs opérations: • Synchronisation coopérative: lorsqu' un processus attend la fin de l’exécution d' un autre avant de poursuivre son exécution. • Synchronisation compétitive: lorsque plusieurs processus utilise la même ressource. Il faut alors disposer d' un mécanisme d’exclusion mutuelle afin d’éviter que les processus interfèrent entre eux – la communication des données entre processus: en utilisant des mécanismes de communication inter-processus définis par le système d’exploitation CSI 2520, Hiver 2007

Fil d’exécution • Un fil d’exécution (thread) est une séquence d’exécution pouvant ou non

Fil d’exécution • Un fil d’exécution (thread) est une séquence d’exécution pouvant ou non interagir avec d’autres fils • Les fils partagent souvent les même variables • Les fils ont souvent (mais pas nécessairement) une durée de vie limitée • Un fil peut être bloqué: – Si il désire utiliser des variables partagées avec d’autres fils – Si il doit attendre des résultats d’un autre fil • Une application se subdivise en processus et un processus peut être composé de fils • Les processus sont généralement créés lors de la conception de l’architecture alors que les fils sont créés lors de la phase de programmation CSI 2520, Hiver 2007

Fils en C++ • En utilisant – Afx. Begin. Thread(fonction, parametre); • Le paramètre

Fils en C++ • En utilisant – Afx. Begin. Thread(fonction, parametre); • Le paramètre est un pointeur à des void • La fonction transmise a comme signature – UINT fonction(LPVOID connection. P); CSI 2520, Hiver 2007

Exemple class CMy. Thread {. . . public: static UINT Thread. Proc( LPVOID param

Exemple class CMy. Thread {. . . public: static UINT Thread. Proc( LPVOID param ); private: UINT Do. Thread. Job(); }; UINT CMy. Thread: : Thread. Proc( LPVOID param ) { // Get the "this" pointer CMy. Thread * p. This = reinterpret_cast<CMy. Thread *>(param); UINT CMy. Thread: : Do. Thread. Job() { //. . . Can call member functions here } // Instance of the thread class CMy. Thread my. Thread; Afx. Begin. Thread( CMy. Thread: : Thread. Proc, reinterpret_cast<LPVOID>( &my. Thread)); // Route to non-static member function return p. Instance->Do. Thread. Job(); } CSI 2520, Hiver 2007

Fils en Java public class Hello. Runnable implements Runnable { public void run() {

Fils en Java public class Hello. Runnable implements Runnable { public void run() { System. out. println("Hello from a thread!"); } public class Hello. Thread extends Thread { public static void main(String args[]) { (new Thread(new Hello. Runnable())). start(); } public void run() { System. out. println("Hello from a thread!"); } } public static void main(String args[]) { (new Hello. Thread()). start(); } } CSI 2520, Hiver 2007

Contrôle des fils Hello. Thread thread = Hello. Thread Fil(); thread. start(); // demarrer

Contrôle des fils Hello. Thread thread = Hello. Thread Fil(); thread. start(); // demarrer le fil d’execution thread. sleep( 3000 ); // mettre un fil en pause thread. is. Alive(); // verifier si un fil est actif thread. interrupt(); // interrompre un fil thread. join(); // attendre la terminaison d’un fil CSI 2520, Hiver 2007

Exemple class Example extends Thread { volatile boolean stop = false; public static void

Exemple class Example extends Thread { volatile boolean stop = false; public static void main( String args[] ) throws Exception { Example 2 thread = new Example 2(); System. out. println( "Starting thread. . . " ); thread. start(); Thread. sleep( 3000 ); System. out. println( "Asking thread to stop. . . " ); thread. stop = true; Thread. sleep( 3000 ); System. out. println( "Stopping application. . . " ); System. exit( 0 ); } public void run() { while ( !stop ) { System. out. println( "Thread is running. . . " ); sleep( 1000 ); } System. out. println( "Thread exiting under request. . . " ); } } CSI 2520, Hiver 2007

Niveaux de concurrence • • au niveau des énoncés: une série d' énoncés sont

Niveaux de concurrence • • au niveau des énoncés: une série d' énoncés sont exécutés de façon concurrente, le processus principal suspend alors son exécution. Chacun des processus ainsi créés partagent le même ensemble de données (Open. MP) au niveau des sous-programmes: un processus commande alors la création d’un autre processus dont la tâche consiste à exécuter un certain sousprogramme. Une fois le processus lancé, le processus appelant continue son exécution. Un mécanisme de synchronisation doit toutefois être disponible. au niveau des objets: chacune des instances d' une classe devient une entité concurrente; il y a alors exécution concurrente d' une de ses méthodes. Les attributs ne sont pas partagés. au niveau des programmes: ceci se produit lorsqu' un processus parent a la capacité de lancer un ou plusieurs processus enfant. Il doit toutefois exister un moyen de connaître l' identité d' un processus. Les données peuvent être partagées ou non. CSI 2520, Hiver 2007

Type de concurrence • Physique: lorsque plusieurs processeurs se partagent les différents processus •

Type de concurrence • Physique: lorsque plusieurs processeurs se partagent les différents processus • Logique: lorsque plusieurs processus se partagent le temps d' exécution sur un seul processeur. • Distribué: lorsque plusieurs machines constituées en réseau se partagent les processus. CSI 2520, Hiver 2007

Moniteur • Un moniteur est une abstraction qui contient les données partagées ainsi que

Moniteur • Un moniteur est une abstraction qui contient les données partagées ainsi que les procédures qui accèdent à ces données • La synchronisation est alors réalisée implicitement en n’autorisant qu’un accès à la fois au moniteur • Lorsque le moniteur est occupé, tous les processus en attente pour accès sont placés dans une file • En réalisant un appel à une opération du moniteur, un processus obtient des droits exclusifs d' accès aux ressources du moniteur. Cette exclusivité demeure jusqu’à ce que l’opération soit complétée ou jusqu’à ce que ce processus se place en attente CSI 2520, Hiver 2007

Java et moniteurs • En Java, tous les objets ont un moniteur intrinsèque associé

Java et moniteurs • En Java, tous les objets ont un moniteur intrinsèque associé – Méthodes synchronisées – Blocs synchronisés • avec l’énoncé synchronized(object) • La file d’attente est gérée par la machine virtuelle Java • Jusqu’à 50 fois plus lente que les méthodes nonsynchronisées CSI 2520, Hiver 2007

Exemple: un bassin d’objets protected Object[] items =. . . whatever kinds of items

Exemple: un bassin d’objets protected Object[] items =. . . whatever kinds of items being managed protected boolean[] used = new boolean[MAX_AVAILABLE]; protected synchronized Object get. Next. Available. Item() { for (int i = 0; i < MAX_AVAILABLE; ++i) { if (!used[i]) { used[i] = true; return items[i]; } } return null; // not reached } protected synchronized boolean mark. As. Unused(Object item) { for (int i = 0; i < MAX_AVAILABLE; ++i) { if (item == items[i]) { if (used[i]) { used[i] = false; return true; } else return false; } } CSI 2520, Hiver 2007

Exemple: Le producteur/consommateur private Linked. List list = new Linked. List(); public void produce()

Exemple: Le producteur/consommateur private Linked. List list = new Linked. List(); public void produce() { int len = 0; synchronized(list) { // impose un verrou sur la liste Object just. Produced = new Object(); list. add. First(just. Produced); len = list. size(); list. notify. All(); // avise les autres fils } // libere le verrou System. out. println("List size now " + len); } CSI 2520, Hiver 2007

Exemple: Le producteur/consommateur public void consume() { Object obj = null; int len =

Exemple: Le producteur/consommateur public void consume() { Object obj = null; int len = 0; synchronized(list) { while (list. size() == 0) { try { list. wait(); // suspend le fil } catch (Interrupted. Exception ex) { return; } } obj = list. remove. Last(); len = list. size(); } System. out. println("Consuming object " + obj); System. out. println("List size now " + len); } CSI 2520, Hiver 2007

Sémaphore • Une sémaphore est un mécanisme qui permet la synchronisation et le partage

Sémaphore • Une sémaphore est un mécanisme qui permet la synchronisation et le partage de ressource entre processus P(Semaphore s) { wait until s } V(Semaphore s) { s : = s+1; } Init(Semaphore // Acquire Resource > 0, then s : = s-1; // Release Resource s, Integer v) { s : = v; } CSI 2520, Hiver 2007

Mutex • Un mutex permet de verrouiller une ressource pendant qu’un fil y accède

Mutex • Un mutex permet de verrouiller une ressource pendant qu’un fil y accède • Un mutex est donc associé à une ressource (une classe) • Implementés en utilisant des sémaphore binaires CSI 2520, Hiver 2007

Exemple C++ CMutex mutex; // this is the Mutex class // This is the

Exemple C++ CMutex mutex; // this is the Mutex class // This is the synchronization class // when you need to control access // to one resource using a given mutex CSingle. Lock mulock(&mutex); if (mulock. Lock(1000)) { // will block until // the Mutex is available // exclusive access to this block conteneur. erase(id); } mulock. Unlock(); // release the Mutex CSI 2520, Hiver 2007

Exemple: Accès exclusif à un fichier CMutex mutex; // one attribute // of the

Exemple: Accès exclusif à un fichier CMutex mutex; // one attribute // of the class void reader() { void writer() { CSingle. Lock mulock(&mutex); if (mulock. Lock(1000)) { // do something… read_file(); } // do something… write_file(); } } mulock. Unlock(); } CSI 2520, Hiver 2007

Exemple: Accès à un fichier • Lecture partagée – Il y a un nombre

Exemple: Accès à un fichier • Lecture partagée – Il y a un nombre maximum de fils pouvant lire • Écriture exclusive – Un seul fil doit écrire à la fois – Le fil écrivant doit attendre que tous les fils lisant terminent import java. util. concurrent. Semaphore const int Max. Readers = 32; Semaphore semaphore(Max. Readers); // Max. Readers is the total number of permits void Reader. Thread: : run() { semaphore. acquire(); // Acquires a permit from this semaphore, // blocking until one is available; read_file(); semaphore. release(); // Release a permit } void Writer. Thread: : run() // should be synchronized // if more than one writer { for (int i = 0; i < Max. Readers; ++i) semaphore. acquire(); // acquisition graduelle de ressource write_file(); semaphore. release(Max. Readers); // Release all permits } CSI 2520, Hiver 2007

Attention aux ‘deadlocks ’ ! • Se produit lorsque deux fils vérouillent chacun une

Attention aux ‘deadlocks ’ ! • Se produit lorsque deux fils vérouillent chacun une ressource et veulent aussi accéder à la ressource de l’autre – Ex: Le diner des philosophes CSI 2520, Hiver 2007

Exemple class Attention { public synchronized void ceci(Attention obj) {. . . obj. cela(this);

Exemple class Attention { public synchronized void ceci(Attention obj) {. . . obj. cela(this); } public synchronized void cela(Attention obj) { … } } CSI 2520, Hiver 2007