Download Proving Correctness of Concurrent Programs: Techniques and Challenges and more Slides Object Oriented Programming in PDF only on Docsity!
Proving things about
concurrent programs
Overview
- Two weeks ago we looked at techniques for proving things about recursive algorithms - We saw that in general, recursion matches with the notion of an inductive proof
- How can one reason about a concurrent algorithm?
- We still want proofs of correctness
- Techniques aren’t identical but we often use induction
- Induction isn’t the only way to prove things
Safety and Liveness
- Leslie Lamport suggested that we think about the question in terms of safety and liveness - A program is safe if nothing bad happens. The guarantee that concurrently accessed memory will be locked first is a safety property. - The property is also called mutual exclusion - A program is live if good things eventually happen. The guarantee that all threads get to make progress is a liveness property
Proper synchronization
- Consider a program with multiple threads in it
- Perhaps threads T1 and T
- They share some objects
- First, we need to ask if the shared objects are thread safe
- Every access protected by synchronized() { … }
Hardware needs synchronization too!
- Without synchronization locks, if a thread updates objects the thread itself always sees the exact updates in the order they were done
- But other threads on other cores could see them out of order and could see some updates but not others
- Java volatile keyword: warns compiler that a global variable isn’t protected by synchronization. Volatile is difficult to use correctly.
Interleavings
- Suppose that a program correctly locks all accesses to shared objects, or uses volatile correctly
- Would it now be safe?
- Issue that arises involves interleavings
Determinism
- What Lamport would call a safety property
- A program is deterministic if it produces the identical results every time it is run with identical input - This is desirable
- A program is non deterministic if the same inputs sometimes result in different outcomes - This is confusing and can signal problems
Linearizability
- Concept was proposed by Wing and Herlihy
- Start with your concurrent program
- But prove that it behaves like a non-concurrent program that does the same operations in some “linear” order - Idea behind proof: if the effect of two executions is
the same, then we can treat them as equivalent
- Program is concurrent yet acts deterministic
- Not all programs are linearizable
Deadlock
- Recall from last week
- Deadlock depends on four conditions
- A wait-for cycle
- Locks that are held until the thread finishes what it wants to do, not released
- No preemption of locks
- Mutual exclusion
Revisit: Deadlock avoidance
- Suppose that threads acquire locks in some standard
order. Thm: deadlock cannot occur!
- Slightly oversimplified proof: A deadlock means that there is
some cycle of threads A, B…. T each waiting for the next to take
some action.
- Consider thread A and assume A holds lock X a
- A is waiting on B: A wants a lock Xb and B holds that lock.
- Now look at B: it holds Xb and wants Xc.
- We eventually get to thread T that holds Xt and wants Xa
- But per our rules Xa < Xb < …. Xt < Xa: a contradiction! QED
- Notice that this is similar to an inductive argument
Paris traffic circles: Deadlock in action
- Paris has a strange rule at some traffic circles: priorité a droite
- Traffic circles around, say, the Arc de Triomphe
- Roads enter from the right
- You must yield to let them enter
Paris traffic circle: priorité a droite
- An issue at Place d’Etoile and Place Victor Hugo (rest of France uses priorité a gauche )
- Think of cars as threads and “space” as objects
- If thread A occupies a space that thread B wishes to enter, then B waits for A
- Under this rule, deadlocks can form!
- To see this, look for a wait-for cycle
Why is priorité a droite a bad rule?
Why is priorité a droite a bad rule?
Ooh la la! Quel
catastrophe!