diff --git a/presentation/codes/concurrent/src/main.rs b/presentation/codes/concurrent/src/main.rs
index 611c6e920954244e7ff297d51ac6a9a5387b127b..2e4fa8feafeebb6279cc3ebe825aaf612551dc3d 100644
--- a/presentation/codes/concurrent/src/main.rs
+++ b/presentation/codes/concurrent/src/main.rs
@@ -1,17 +1,92 @@
 use std::thread;
+use std::sync::Arc;
 
-fn main() {
+fn move_borrow() {
+    // // cannot borrow v:
+    // // comportement possible: le programme a fini avant qu'on ait pu faire un push par exemple.
+    // let mut v = Vec::new();
+    // let loc = thread::spawn(|| {
+    //     v.push(1);
+    // });
+    // v.push(4);
+    // println!("{:?}", loc.join().unwrap());
 
-    let loc = thread::spawn( || {
-        "world"
-    });
-    println!("Hello {}!", loc.join().unwrap());
+    // // v moved in thread, cannot be used elsewhere
+    // let mut v = Vec::new();
+    // let loc = thread::spawn(move || {
+    //     v.push(1);
+    //     v
+    // });
+    // v.push(4);
+    // println!("{:?}", loc.join().unwrap());
 
+    // here it works
     let mut v = Vec::new();
     let loc = thread::spawn(move || {
         v.push(1);
         v
     });
     println!("{:?}", loc.join().unwrap());
+}
+
+fn share_with_rc() {
+    // let v = Rc::new(vec![1,2,3,4]); // reference counted
+    // let v_cloned = v.clone(); // create a new reference
+    //
+    // // rc cannot be sent between threads safely.
+    // thread::spawn(move || {
+    //     println!("{:?}", v);
+    // });
+
+    // // Arc can be sent between threads safely.
+    // let v = Arc::new(vec![1,2,3,4]); // reference counted
+    // let v_cloned = v.clone(); // create a new reference
+    // thread::spawn(move || {
+    //     println!("{:?}", v);
+    // });
+
+    // println!("{:?}", v_cloned);
+
+    // Arc can be sent between threads safely.
+    let v = Arc::new(vec![1,2,3,4]); // reference counted
+    let v_cloned = v.clone(); // create a new reference
+    thread::spawn(move || {
+        println!("{:?}", v);
+    });
+
+    println!("{:?}", v_cloned);
+
+}
+
+fn spawn_unordered_not_finishing() {
+    for i in 0..10 {
+        let loc = thread::spawn(move || {
+            println!("Hello from child thread {}!", i);
+        });
+    }
+
+    for i in 0..10 {
+        println!("Hello {} from main thread!", i);
+    }
+}
+
+fn spawn_unordered_join() {
+    let mut handles = Vec::new();
+    for i in 0..10 {
+        handles.push(thread::spawn(move || {
+            println!("Hello from child thread {}!", i);
+        }));
+    }
+
+    for h in handles {
+        h.join();
+    }
+}
+
+fn main() {
+    spawn_unordered_not_finishing()
+    
+    spawn_unordered_join();
 
+    // share_with_rc();
 }
diff --git a/presentation/intro.md b/presentation/intro.md
index a80fa75108bbd40751790e1e869d5ae05867dde4..0965732612d03e3cb99b6e2b26d22d4ca2e45cca 100644
--- a/presentation/intro.md
+++ b/presentation/intro.md
@@ -393,12 +393,36 @@ Les "data-race" surviennent quand:
 
 . . .
 
-Le partage des données et la mutation est incompatible en Rust.
+Le partage des données et la mutation est incompatible en Rust: leur absence est garantie à la compilation
 
-## Rust prévient à la compilation
+# La concurrence en pratique
 
-- Les accès concurrents.
-- 
+## thread::spawn .join()
+
+La sytaxe pour créer un `thread` et le synchroniser
+avec le thread principal est `thread::spawn` et `.join()`
+
+<pre><code data-trim="hljs rust" class="lang-rust">
+fn main() {
+    let v = vec![1,2,3];
+
+    let handle = thread::spawn(move || { // si on enlève move...
+		println!("{:?}", v);             // ça ne compile plus
+	});
+
+	handle.join();
+}
+</code></pre>
+
+. . .
+
+Sans le `move` on peut avoir des **accès concurrents** aux données.
+
+## std::rc::Rc
+
+
+
+## std::sync::Arc
 
 # And many more