Rust atomics study group: Chapter 1
Remember when I said we were starting a study group for "Rust Atomics and Locks"? Well, plot twist: we're not just reading the book together and nodding sagely.
Oh no, that would be far too civilised. We're going full interactive, hands-on, break-things-and-fix-them mode. đĽ
After spending way too much time thinking about how people actually learn hard stuff (and by "way too much time," I mean procrastinating on actually writing this post and then also reading Chapters 2 and even 3), I've put together a proper session plan for our first chapter. And by "proper," I mean "something that will hopefully result in more learning, even having some fun, than crying"
The Core Problem With Learning Concurrency
Here's the thing about concurrent programming: you can read about it, you can nod along, you can even copy-paste working examples. But until you've actually felt the frustration of a deadlock you created yourself, or debugged a race condition that only happens one time in fifty, or spent an hour figuring out why your "obviously correct" code makes the compiler angry, you don't really get it. I know this is something that never really happened to us. Cough, cough... Sure. đ
It's like learning to ride a bike by reading about it. Sure, you'll know what pedals do, but you won't have that visceral understanding of balance until you've fallen off a few times. (Don't worry, in our case, the falls are just compiler errors, not actual injuries. Probably.)
For Chapter 1, we're creating a session that allows us to experience the concepts rather than just reading about them. Think of it as the difference between watching cooking shows and actually burning, ops, cooking our dinner (we shouldn't burn our CPUs, though).
What Chapter 1 Is Actually About
Before we dive into how we're learning it, let's talk about what we're learning. Chapter 1 is called "Basics of Rust Concurrency," and while "basics" might sound gentle, Mara Bos (the author of the book, just as a reminder) doesn't mess around. This chapter lays down the foundational concepts that everything else is built upon. So, please don't underestimate it and take a good read at it (i.e., don't do what I did the first time I read it).
We're talking about threads and how Rust's ownership system extends into concurrent programming. We're exploring why some types can be sent between threads while others can't, and what those magical Send and Sync traits actually mean. We're looking at interior mutabilityâwhich sounds like a description of my emotional state when debugging concurrency issues, but is actually about how to safely mutate data through shared references..
And then we get into the synchronisation primitives: Mutex, RwLock, condition variables, and thread parking. These are the tools we'll use to build concurrent systems, and understanding them deeply means knowing not just how to use them, but why they exist and what problems they solve.
The key insight of Chapter 1 is this: Rust's type system isn't just preventing data races by being annoying (let's be fair: it's pretty damn annoying, and I'm being very polite here!!). It's actually encoding deep truths about concurrent programming at the type level. When the compiler refuses to let you send an Rc between threads, it's not being pedanticâit's proving to you that your code is not safe (or some other words still starting with s...). That proof is worth understanding!
How We're Actually Going to Learn This
Right, so here's the structure for our first session. Fair warning: this is going to last at least two or three hours, and yes, that's longer than an average meetup. If needed, it is a good idea to split the session into more than one, especially if the group is quite large and there are different levels of Rust and concurrency knowledge. We're not just sitting through slides, I didn't prepare any (and believe me, you'd thank me for that :-D): we're actually doing things. The real, one and only goal of all this is to have everyone, almost, on the same page at the end of every session. Plus, have fun and eat a lot of pizza. #justsaying
I have an idea for these sessions: I'm trying, and hopefully, not miserably failing at the first attempt, to time-box each part. Let's engage in focused work (hold my beer for a moment), achieve the results we planned for, and then take a break or chat before moving on to the next phase.
The Confusion Harvest (20-30 minutes)
This is a new one (I guess). We start by making confusion visible. Okay, let me explain it for a moment. Everyone writes down what confused them when reading the chapter. No judgment, no "obvious" statements, just honest "I have no idea what this means" admissions. Disclaimer: Ultimately, it doesn't matter; it's about doing real work and sharing together. We're creating a shared confusion board/paper because here's a secret: if something confused you, it confused at least three other people who were too polite/afraid to ask.
This isn't just therapy (though it might feel like it, and work better than most of them). By surfacing confusion early, we can address the concepts that truly matter to our group, rather than what someone might think matters! Additionally, each session may differ from the others.
The Send/Sync Discovery (30-45 minutes)
This is where things get interesting. Instead of explaining what Send and Sync mean, we're going to discover it through what I'm calling "Compilation Archaeology" (or compiling without a compiler). We are starting with three pieces of broken code, and the task is to predict the error that will occur before compiling.
The first snippet tries to send an Rc between threads. The second tries to share a Cell with Arc. The third shows the solution with Mutex. But here's the thing: we're working in small groups, predicting the errors, and then discussing why the compiler is angry. We're not just reading error messagesâwe're building intuition about what the type system is protecting you from.
By the time we're done, you won't just know that "Rc isn't Send"âyou'll understand why that restriction exists and what disaster would happen if it didn't. That's the difference between memorising and understanding.
The Human Mutex Protocol (30-45 minutes)
This is my favourite part because it could turn out like a big mess, and yes, it's exactly what it sounds like. We're acting out how a mutex works with actual humans (real or vrtual) playing the roles of threads, the mutex, and shared data.
First, we do it without the mutex to see what goes wrong. Multiple "threads" (people) try to increment a number on a whiteboard simultaneously, and chaos ensues (hopefully still in a civil way, but let's remove all the scissors and knives). The number ends up incorrect due to race conditions, which you can literally see happening.
Then we introduce the mutex protocol: you need to hold a physical token to access the data. Suddenly, everything works, but you also feel the pain of waiting for someone else to release the lock. Again, please let's keep it civil; we don't need to fight for the token. When you've experienced that frustration physically, you understand why holding locks for too long kills performance.
After the optional but funny physical demonstration, we implement it in code. But now we have a mental modelâwe know what the MutexGuard is doing because we held the token ourselves. And when we deliberately introduce a bug (sleeping while holding the lock), we can predict precisely what will happen to performance because we've felt it.
This is embodied learning, and it sticks in a way that reading documentation never does. Plus, it should make this concept funnier and easier to comprehend.
The Condvar Kata (30-45 minutes)
Condition variables (or condvar for friends) are where things get properly tricky (though, we are using Rust :D). They serve as the coordination mechanism for "wait until something happens to the data," and they're surprisingly subtle to use correctly, despite being a relatively simple concept.
So naturally, we are starting with some broken code to fix. It's a producer-consumer pattern with a bugâit uses if instead of while when checking if the queue is empty. The job is to determine why this matters, what a "spurious wakeup" means, and how to resolve it.
Then we extend it: multiple producers, multiple consumers, and the trick part is to make sure no items get lost and no threads wait forever (what could possibly go wrong here?). This is where we learn by debugging, which is how we'll learn in real projects too (let's assume nobody here will simply ask an AI bot to solve it for us, right?).
The pattern here is deliberate struggle followed by group synthesis. We don't learn condition variables by reading about themâyou learn by messing them up, fixing them, and explaining to someone else why your fix works (good luck with that).
The Integration Challenge (x minutes)
By now, we've seen threads, Send/Sync, mutexes, and condition variables. I admit: my brain will already be asking for a timeout, but let's proceed. Time to put everything together. The challenge is to build a three-stage pipeline: a reader generates numbers, a processor transforms them, and a writer outputs results. Each stage runs in its own thread with bounded queues between them. Reading this back, I think I was drinking too much coffee when I wrote that, and got "slightly" excited, but it is an experiment: let's see how it goes.
This isn't a toy exampleâthis is the kind of architecture we'd actually use (without always depending on someone else's crate). We need to think about domain boundaries, invariants, and synchronisation points. Where do the mutexes go? How do we signal completion? What happens to backpressure (nothing related to your back pain, or at least not directly)?
We're not expecting everyone to finish in thirty minutes or even an hour. The point is to struggle with design decisions, make choices, and defend them to your group. That's where the learning happensânot in having the perfect solution, but in reasoning through trade-offs. It could be a take-home task or something to be addressed in the next session, where an open discussion could help compare different solutions.
Mental Model Synthesis (15 minutes)
If we have some spare time and our brain is not completely melted, we can try to close by drawing concept maps connecting everything we've learned: threads, Send, Sync, Arc, Mutex, Condvar, and how they all relate. This forces us to organise the knowledge we've built throughout the session.
Then we do a group reflection, nothing too fancy or hypstery: what clicked, what's still fuzzy, what surprised you. At this point, adding some drinks and pizza will make it even better (not biased at all!!).
Why This Format Works
Actually.. not a clue! đ
I copied it from a guy on X (twitter). Just kidding...
Research on learningâactual peer-reviewed science (we need to put at least one thing about science or research, in every post to look serious, right?), not just my opinionsâshows that active learning beats passive learning by a massive margin. Lecturing is the least effective method for teaching complex topics. What works is constructive struggle: trying something, failing, getting feedback, and trying again.
This format follows that pattern deliberately. Every activity involves doing something: predicting errors, acting out protocols, debugging code, and building systems. You're not sitting there while I explain things. We're building understanding together through experience.
The social aspect matters too. When you explain something to another person, you're forced to organise your thoughts coherently. When you debate a design decision with a peer, you examine your assumptions. When someone else is confused about something you think you understand, teaching them cements your knowledge.
And critically: confusion is part of the process, not a failure. By starting with the Confusion Harvest, we're establishing that it's not just okay to be confusedâit's expected and valuable. It will create a safe space for everyone to experiment, to learn and have fun.
The Principles-First Philosophy
One thing that's important to me about this study group is that we're not just learning Rust APIs. We're learning the fundamental principles of concurrent programming that work in any (proper) language (so, JavaScript, Python & C. excluded, gnegne đ ).
Before we touch Mutex, we talk about the problem: what happens when multiple threads access shared memory? Why is this undefined behaviour? What guarantees do we need? Only then do we look at how Rust solves it, and try not to rely too much on the type system and the borrow checker (which, in these cases, are a huge help).
This means that when we encounter a new concurrency challenge, we won't just search for the right "sorcery". We'll reason from first principles: what are the invariants? What needs to be synchronised? What are the performance trade-offs?
Mara Bos does this brilliantly in the book, and we're extending that approach into how we teach each other. Domain-driven design thinking (one of my fixations) meets systems programming: identify your entities, understand your invariants, design your boundaries.
What You Need to Do Before the Session
Honestly, not much. Read Chapter 1 of the bookâit's available free online at marabos.nl/atomics. Take notes on what confuses you. That's it.
Well, okay, also make sure you have Rust installed and can compile basic programs, your favourite editor/IDE and possibly a working debugger. We'll be writing code, and while we can use the Rust Playground for quick experiments, having a local setup is better.
But seriously, come with your confusions ready. The session is designed around making those confusions productive. If you understand everything already, you're either lying or you should be teaching the session!
The Hybrid Format
As I mentioned in the original announcement, we're implementing a hybrid approach: in-person at the Rust London Hack & Learn sessions for those who can attend, and virtual via video call for everyone else.
For virtual folks, we'll try to adapt to the situation, but the idea is to use breakout rooms heavily. Pair programming activities work just as well remotelyâsometimes even better, actually, because screen sharing makes it easier to debug together (too optimistic?). The Human Mutex Protocol is the one activity that's trickier virtually, but we'll adapt it with a shared document and some creative role-playing (plus it is still optional).
All materialsâcode snippets, exercises, facilitation notesâwill be in our GitHub repository. Even if you can't attend live, you can work through everything at your own pace or organise your own local session with friends. You need to be your own provider of pizza and beer (and this could be even better, cause you will have only your favourite ones).
What Happens After Chapter 1
If this session format works (and I'm cautiously optimistic it will), we'll continue with the same structure for subsequent chapters. Chapter 2 on atomics, Chapter 3 on memory orderingâeach will have its own interactive activities designed around the core concepts.
The beauty of this approach is that it scales. Once we've established the pattern of active learning, each chapter builds on the mental models from previous ones. By the time we get to building lock-free data structures in later chapters, we'll have the foundational understanding to tackle them.
Plus, we'll iterate. After each session, we'll do a quick retrospective: what worked, what didn't, what to adjust (in REAL Agile way, not the Enterprise Agile you are using at work). This is as much an experiment in collaborative learning as it is a study group. We're figuring this out together (AKA, next chapters are up to you to create the exercises :-D ).
The Real Goal Here
Look, I'll be honest: I could read this book alone. You could too. We could all individually struggle through the concepts, eventually figure them out (if we're lucky), and move on with our lives.
But there's something valuable about learning together that goes beyond merely understanding the material. It's about building a community of people who can think about concurrent programming. It's about creating that space where asking "but why does this work?" is encouraged, not dismissed.
When you're working on a real project and hit a concurrency bug, you'll remember the Human Mutex Protocol or the Condvar Kata, hopefully not the pain. More importantly, you'll have peers who understand the same concepts and can help you debug. That network of shared understanding is worth more than any individual knowledge.
So yes, this is a study group for "Rust Atomics and Locks." But really, it's an experiment in how we learn hard things together, eventually have fun and an additional excuse to have more pizza and drinks (despite partner complaints and doctor orders).
See You There
Our first session is coming up soon (exact date and logistics in the GitHub repo). Whether you're joining us in person in London or virtually from anywhere, bring your curiosity, your confusion, and a willingness to break some code.
Fair warning: by the end of this session, you will have experienced a race condition, acted out being a mutex, and possibly developed strong opinions about condition variable APIs. These are the risks we take in the pursuit of knowledge.
Also, there will almost certainly be (Italian, so no pineapple and no chicken) pizza at the in-person session. I'm not saying that should influence your decision to attend, but I'm not not saying it either. đ
See you in the threads (pun absolutely intended).
Happy hacking!
P.S. If you're curious about the detailed session plan, facilitation notes, and all the code snippets we'll be using, they're/will all be in the repository under chapters/ch01-basics/. Feel free to look ahead, though I'd recommend experiencing the activities live if you canâthere's something about the struggle that makes the insights stick.
P.P.S. If you have ideas for activities or would like to help facilitate a session, please reach out on GitHub! This is a collaborative experiment, and the more perspectives we have on how to teach these concepts, the better we'll all learn.
P.P.P.S. Yes, I'm aware that spending this much time designing learning activities means I've avoided actually reading Chapter 2. Don't judge me. We all have our own coping mechanisms for dealing with difficult material. đ