Race condition
- When a resource is acquired by two or more processed at the same time
- It may lead to resource's inconsistency
- E.g., two functions incrementing a counter at the same time
class Main {
public static void main(String[] args) throws InterruptedException {
counter = new Counter();
Runnable job = () -> {
for (int i = 0; i <= 1000; i++) {
counter.increment();
}
};
Thread t1 = new Thread(job);
Thread t2 = new Thread(job);
t1.start();
t2.start();
t1.join()
t2.join()
System.out.println(c.count); // won't be equal to 2000 (will be around ~1800)
}
}
class Counter {
int count = 0;
// public synchronized void increment() { // this would ensure that this method can be called only once per time
public void increment() {
count++;
}
}
Handling Race Conditions
- Technique to prevent two or more threads to access the same resource at same time
Mutex (Mutual exclusion)
Mutex is an object owned by a thread, so there is a ownership in mutex. Mutex allows only one thread to access the resource
- The resource uses then a
Mutual Exclusion Object
(mutex) that acts like a lock to signalize that the resource is being used -
If a process tries to access the resource while it's locked, it will error out
-
Cons
- May slow down the system since the resource access is now bottlenecked
Semaphore (Signaling)
Semaphore is a signaling mechanism. It allows a maximum number of threads to access shared resources
- While a signal is on, no other resource can access it
-
If a process tries to access the resource while the signal is on, it will wait (with light turned off) until the resource it freed
-
Uses the Dekkers's Algorithm to avoid deadlocks
my_light = on
while other_light == on:
if current_turn == other:
my_light = off
wait until current_turn = my
my_light = on
access resource
current_turn = other
my_light = off