diff --git a/mutex_barriers/ex1/ex1.md b/mutex_barriers/ex1/ex1.md
new file mode 100644
index 0000000000000000000000000000000000000000..c09d214da9ea7d7b3e82bfd4cc5a1a29003db0a0
--- /dev/null
+++ b/mutex_barriers/ex1/ex1.md
@@ -0,0 +1,64 @@
+# Exercice 1
+
+Le coeur des 3 threads ci-dessous (appelés en boucle) peuvent avoir grand nombre d’occurrences
+chacun. Les mutex sont déjà initialisés correctement. Les appels aux ressources X(), Y() et Z() ne
+sont pas thread-safe.
+
+## Coeur du thread A
+
+```c
+mutex_lock(&mutex_x);
+use_X();
+mutex_unlock(&mutex_x);
+```
+
+## Coeur du thread B
+
+```c
+mutex_lock(&mutex_y);
+use_Y();
+mutex_unlock(&mutex_y)
+```
+
+## Coeur du thread C
+
+```c
+mutex_lock(&mutex_z);
+use_Z();
+mutex_unlock(&mutex_z)
+```
+
+## Exécution
+
+avec :
+```c
+use_X() {
+    X() ;
+    mutex_lock(&mutex_y);
+    Y();
+    mutex_unlock(&mutex_y);
+}
+
+use_Y() {
+    Y() ;
+    mutex_lock(&mutex_z);
+    Z();
+    mutex_unlock(&mutex_z);
+}
+
+use_Z() {
+    Z() ;
+    mutex_lock(&mutex_x);
+    X();
+    mutex_unlock(&mutex_x);
+}
+```
+
+## Questions
+
+1. Mais cette solution peut présenter un dead-lock . Démontrez-le de façon explicite.
+
+2. Est-ce que la solution proposée ci-dessus fonctionnerait si seulement les version A et B des
+threads étaient utilisés (à plusieurs exemplaires) ?
+
+3. Corrigez la solution complète, **en conservant des sections critiques les plus courtes possibles.**
diff --git a/mutex_barriers/ex2/.gitignore b/mutex_barriers/ex2/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..b6de771d2fff3a218dbc1b3de5b6b6cc1dc54e08
--- /dev/null
+++ b/mutex_barriers/ex2/.gitignore
@@ -0,0 +1,2 @@
+*.o
+prog
diff --git a/mutex_barriers/ex2/Makefile b/mutex_barriers/ex2/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..5dadd7ee2331424c5f77b2a1408f2cfc22f1f613
--- /dev/null
+++ b/mutex_barriers/ex2/Makefile
@@ -0,0 +1,21 @@
+CC := clang
+CFLAGS := -g -pedantic -std=gnu11 -Wall -Wextra
+LDFLAGS := -fsanitize=address,leak,undefined -lpthread
+TARGET := prog
+
+all: $(TARGET)
+
+$(TARGET): prog.o
+	$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)
+
+%.o: %.c
+	$(CC) $(CFLAGS) -c $<
+
+.PHONY: clean
+
+clean:
+	rm -f *.o $(TARGET)
+
+.PHONY: rebuild
+
+rebuild: clean all
diff --git a/mutex_barriers/ex2/prog.c b/mutex_barriers/ex2/prog.c
new file mode 100644
index 0000000000000000000000000000000000000000..7cd2218aa35d86fd67e27e720acec3bb1881eb6b
--- /dev/null
+++ b/mutex_barriers/ex2/prog.c
@@ -0,0 +1,84 @@
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct {
+    int nb_threads;
+    pthread_mutex_t counter_lock;
+    int counter;
+    pthread_cond_t can_proceed;
+} barrier_t;
+
+barrier_t b;
+
+void barrier_init(barrier_t *b, int count) {
+    if (count < 1) {
+        fprintf(stderr, "Cannot initialize a barrier for less than 1 thread\n");
+        return;
+    }
+
+    b->nb_threads = count;
+    b->counter = 0;
+    pthread_cond_init(&b->can_proceed, NULL);
+
+    pthread_mutexattr_t attr;
+    pthread_mutexattr_init(&attr);
+    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
+
+    pthread_mutex_init(&b->counter_lock, &attr);
+
+    fprintf(stdout, "Barrier has been successfully initialized\n");
+}
+
+void barrier_wait(barrier_t *b) {
+    pthread_mutex_lock(&b->counter_lock);
+
+    b->counter++;
+
+    if (b->counter == b->nb_threads) {
+        b->counter = 0;
+        pthread_cond_broadcast(&b->can_proceed);
+    } else {
+        while (pthread_cond_wait(&b->can_proceed, &b->counter_lock) != 0) {
+        }
+    }
+
+    pthread_mutex_unlock(&b->counter_lock);
+}
+
+void barrier_destroy(barrier_t *b) {
+    pthread_cond_destroy(&b->can_proceed);
+    pthread_mutex_destroy(&b->counter_lock);
+}
+
+void *routine(void __attribute__((unused)) * arg) {
+    fprintf(stdout, "2nd thread BEFORE barrier\n");
+    barrier_wait(&b);
+    fprintf(stdout, "2nd thread AFTER barrier\n");
+    return NULL;
+}
+
+int main(void) {
+    fprintf(stdout, "main thread started\n");
+    barrier_init(&b, 2);
+
+    pthread_t thread;
+    if (pthread_create(&thread, NULL, routine, NULL) == -1) {
+        perror("pthread_create");
+        exit(EXIT_FAILURE);
+    }
+
+    fprintf(stdout, "main thread BEFORE barrier\n");
+    barrier_wait(&b);
+    fprintf(stdout, "main thread AFTER barrier\n");
+
+    if (pthread_join(thread, NULL) == -1) {
+        perror("pthread_join");
+        exit(EXIT_FAILURE);
+    }
+
+    barrier_destroy(&b);
+
+    return EXIT_SUCCESS;
+}