java · level 3 · unit 5 · lesson 2
- meet it
- guess first
- your turn
- fix it
- nailed it
Tap a green word if you get lost.
meet it
Two threads, one counter: a waiting to happen.
count++ looks like one step but is three: read the value, add one, write it back. If two threads read 41 at the same moment, both write 42, and one update is lost. A bug like this, where the result depends on timing, is a race condition.
Races hide. A program can pass a thousand runs, then lose a sale on the busiest day. You cannot test them away, so you design them out.
Mark the method . Each object has one , and a thread must hold it to enter. Others wait their turn, so the read, add and write happen together. Every thread must share the same object, or each has its own lock and nothing is protected.
public class Main {
static class Tills {
private int sales = 0;
synchronized void sell() {
sales++;
}
synchronized int total() { return sales; }
}
static void shift(Tills tills) {
for (int i = 0; i < 50000; i++) {
tills.sell();
}
}
public static void main(String[] args) throws InterruptedException {
Tills shop = new Tills();
Thread morning = new Thread(() -> shift(shop));
Thread evening = new Thread(() -> shift(shop));
morning.start();
evening.start();
morning.join();
evening.join();
System.out.println("Sales: " + shop.total());
}
} Remove synchronized from sell and the total would come out short, by a different amount each run.
guess first
Three gates, one counter. What will this show?
Guess before you run it. Wrong guesses are how you learn, and nothing is marked.
public class Main {
static class Counter {
private int value = 0;
synchronized void add(int amount) { value = value + amount; }
synchronized int get() { return value; }
}
public static void main(String[] args) throws InterruptedException {
Counter visitors = new Counter();
Thread[] gates = new Thread[3];
for (int g = 0; g < 3; g++) {
gates[g] = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
visitors.add(1);
}
});
gates[g].start();
}
for (Thread gate : gates) {
gate.join();
}
System.out.println(visitors.get());
}
}
your turn
Your turn. Guard the family wallet.
On line 4, make deposit safe so only one thread at a time can run it.
output
press run to see what happens
fix it
Half the votes go missing. Can you fix it?
output
press run to see what happens
- Only half the votes arrive. Which
Tallydoes each thread count into? - Line 15 builds a brand new
Tallyfor its thread, so those votes land somewhere nobody looks. - Change
new Tally()on line 15 totally, so both threads share one object, then run.
nailed it
you can share data between threads safely. :D
count++is read, add, write, and threads can interleave it.synchronizedlets one thread at a time hold the object's lock.- Threads must share the same object for the lock to help.
new words in your collection
- race condition
- synchronized
- lock
This lesson isn’t saved. A free account remembers every lesson you finish.