comp3151/9151 foundations of concurrency lecture 8cs3151/17s2/lec/pdf/lecture08la.pdf · critical...

30
Readers and Writers Haskell Operational Semantics COMP3151/9151 Foundations of Concurrency Lecture 8 Liam O’Connor CSE, UNSW (and data61) 8 Sept 2017 1

Upload: others

Post on 22-Mar-2020

2 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

COMP3151/9151 Foundations ofConcurrency Lecture 8

Liam O’Connor

CSE, UNSW (and data61)

8 Sept 2017

1

Page 2: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

Shared DataConsider the Readers and Writers problem from Lecture 6:

Problem

We have a large data structure (i.e. a structure that cannot beupdated in one atomic step) that is shared between some numberof writers who are updating the data structure and some numberof readers who are attempting to retrieve a coherent copy of thedata structure.

Desiderata:

We want atomicity, in that each update happens in one go,and updates-in-progress or partial updates are not observable.

We want consistency, in that any reader that starts after anupdate finishes will see that update.

We want to minimise waiting.

2

Page 3: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

A Crappy Solution

Treat both reads and updates as critical sections — use any oldcritical section solution (mutexes, semaphores, etc.) tosequentialise all reads and writes to the data structure.

Observation

Updates are atomic and reads are consistent — but reads can’thappen concurrently, which leads to unnecessary contention.

3

Page 4: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

A Better Solution

Use a monitor with two condition variables.

See Algorithm 6.12 of the slides or Ben-Ari’s Algorithm 7.4.

Observation

We have atomicity and consistency, and now multiple reads canexecute concurrently. Still, we don’t allow updates to executeconcurrently with reads, to prevent partial updates from beingobserved by a reader.

4

Page 5: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

Reading and Writing

Complication

Now suppose we don’t want readers to wait (much) while an updateis performed. Instead, we’d rather they get an older version of thedata structure.

Trick: Rather than update the data structure in place, a writercreates their own local copy of the data structure, and then merelyupdates the (shared) pointer to the data structure to point to theircopy.Liam: Draw on the board

Atomicity The only shared write is now just to one pointer.

Consistency Reads that start before the pointer update get theolder version, but reads that start after get the latest.

5

Page 6: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

Persistent Data StructuresCopying is O(n) in the worst case, but we can do better for manytree-like types of data structure.

Example (Binary Search Tree)

64

37

20

3 22

40

102

Pointer

64

37

40

42

6

Page 7: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

Persistent Data StructuresCopying is O(n) in the worst case, but we can do better for manytree-like types of data structure.

Example (Binary Search Tree)

64

37

20

3 22

40

102

Pointer

64

37

40

42

7

Page 8: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

Persistent Data StructuresCopying is O(n) in the worst case, but we can do better for manytree-like types of data structure.

Example (Binary Search Tree)

64

37

20

3 22

40

102

Pointer

64

37

40

42

8

Page 9: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

Persistent Data StructuresCopying is O(n) in the worst case, but we can do better for manytree-like types of data structure.

Example (Binary Search Tree)

64

37

20

3 22

40

102

Pointer

64

37

40

42

102

20

3 22

9

Page 10: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

Purely Functional Data Structures

Persistent data structures that exclusively make use of copyingover mutation are called purely functional data structures. Theyare so called because operations on them are best expressed in theform of mathematical functions that, given an input structure,return a new output structure:

insert v Leaf = Branch v Leaf Leafinsert v (Branch x l r) = if v ≤ x then

Branch x (insert v l) relseBranch x l (insert v r)

Purely functional programming languages like Haskell are designedto facilitate programming in this way.

10

Page 11: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

Haskell

Haskell is a programming language where all programs are writtenin the form of immutable definitions. There is no intrinsic notionof time or mutable state. Syntax is mostly derived from simplemathematical notation.

Example (Factorial)

factorial :: Int→ Intfactorial 0 = 1factorial n = n ∗ factorial (n − 1)

Liam: Show more examples, use GHCi a bit

11

Page 12: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

Computing with Functions

Unfortunately, pure functions don’t capture everything we wantfrom computations. Processes have to interact with the user,global state, other processes, and the operating system.We model real processes in Haskell using the IO type.

IO τ =A (possibly effectful) process that, when executed,produces a result of type τ

Note the semantics of evaluation and execution are different things.

12

Page 13: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

Building up IO

pure :: ∀a. a→ IO a(�=) :: ∀a b. IO a→ (a→ IO b)→ IO b

getChar :: IO CharputChar :: Char→ IO ()

Example (Echo)

echo :: IO ()echo = getChar �= (λx . putChar x �= λy . echo)

(here λx . y is notation for an anonymous function that returns y given argument x)

13

Page 14: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

Monadic IO

Monad Laws

Define a sequential composition operatorIO◦ as follows:

(IO◦) :: ∀a b c. (a→ IO b)→ (b → IO c)→ (a→ IO c)

(fIO◦ g) x = f x �= g

We have the following laws to aid reasoning:

Identity fIO◦ pure = f = pure

IO◦ fAssociativity f

IO◦ (gIO◦ h) = (f

IO◦ g)IO◦ h

14

Page 15: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

Do Notation

Haskell defines some convenience notation to make writingprocesses easier.

do x ← P;Q = P �= λx . do Qdo P;Q = P �= λ . do Q

do P = P

Example (Echo, revisited)

echo :: IO ()echo = do

x ← getCharputChar xecho

15

Page 16: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

Adding Concurrency

We can have multiple threads easily enough:

forkIO :: IO () → IO ()

Example (Dueling Printers)

let loop c = do putChar c ; loop cin do forkIO (loop ‘a’); loop ‘z’

But what sort of synchronisation primitives are available?

16

Page 17: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

MVars

The MVar is the simplest synchronisation primitive in Haskell. Itcan be thought of as a shared box which holds at most one value.

Threads must take the value out of a full box to read it, and mustput a value into an empty box to update it.

MVar Functions

newMVar :: ∀a. a→ IO (MVar a) Create a new MVartakeMVar :: ∀a. MVar a→ IO a Read/remove the valueputMVar :: ∀a. MVar a→ a→ IO () Update/insert a value

Taking from an empty MVar or putting into a full one results inblocking.An MVar can be thought of as channel containing at most onevalue.

17

Page 18: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

Readers and WritersWe can treat MVars as shared variables with some definitions:

writeMVar m v = do takeMVar m; putMVar m vreadMVar m = do v ← takeMVar m; putMVar m v ; pure v

problem :: DB → IO ()problem initial = do

db ← newMVar initialwl ← newMVar ()let reader = readMVar db �= · · ·let writer = do

takeMVar wld ← readMVar dblet d ′ = update devaluate d ′

writeMVar db d ′

putMVar wl ()

18

Page 19: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

Fairness

Each MVar has an attached FIFO queue, so GHC Haskell canensure the following fairness property:

No thread can be blocked indefinitely on an MVar unlessanother thread holds that MVar indefinitely.

In LTL, this is something like (where Lm is the queue for MVar m):

(p ∈ Lm ∧�♦putMVar(m))⇒ ♦(p /∈ Lm)

It seems to me that a stronger guarantee can be made, but this is what is stated in the literature.

19

Page 20: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

Evaluation Semantics

The semantics of Haskell’s evaluation are interesting but notparticularly relevant for us. We will assume that it happens quietlywithout a fuss:

β-equivalence (λx . M[x ]) N ≡β M[N]α-equivalence λx . M[x ] ≡α λy . M[y ]η-equivalence λx . M x ≡η M

Let our ambient congruence relation ≡ be ≡αβη enriched with thefollowing extra equations, justified by the monad laws:

pure N �= M ≡ M N(X �= Y )�= Z ≡ X �= (λx . Y x �= Z )X ≡ X �= pure

20

Page 21: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

Processes

This means that a Haskell expression of type IO τ for will boildown to either pure x where x is a value of type τ ; or a�= Mwhere a is some primitive IO action (forkIO p, readMVar v , etc.)and M is some function producing another IO τ . This is the headnormal form for IO expressions.

Definition

Define a language of processes P, which contains all (head-normal)expressions of type IO ().

We want to define the semantics of the execution of theseprocesses. Let’s use operational semantics:

(7→) ⊆ P × P

21

Page 22: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

Semantics for forkIO

To model forkIO, we need to model the parallel execution ofmultiple processes in our process language. We shall add a parallelcomposition operator to the language of processes:

P,Q ::= a�= M| pure ()| P ‖ Q| · · ·

And the following ambient congruence equations:

P ‖ Q ≡ Q ‖ PP ‖ (Q ‖ R) ≡ (P ‖ Q) ‖ R

22

Page 23: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

Semantics for forkIO

If we have multiple processes active, pick one of themnon-deterministically to move:

P 7→ P ′

P ‖ Q 7→ P ′ ‖ Q

The forkIO operation introduces a new process:

(forkIO P �= M) 7→ P ‖ (pure ()�= M)

23

Page 24: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

Semantics for MVars

MVars are modelled as a special type of process, identified by aunique name. Values of MVar type merely contain the name ofthe process, so that putMVar and friends know where to look.

P,Q ::= a�= M| pure ()| P ‖ Q| 〈〉n | 〈v〉n| · · ·

〈〉n ‖ (putMVar n v �= M) 7→ 〈v〉n ‖ (pure ()�= M)

〈v〉n ‖ (takeMVar n�= M) 7→ 〈〉n ‖ (pure v �= M)

24

Page 25: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

Semantics for newMVar

We might think that newMVar should have semantics like this:

(newMVar v �= M) 7→ 〈v〉n ‖ (pure n�= M)(n fresh)

But this approach has a number of problems:

The name n is now globally-scoped, without an explicit binderto introduce it.

It doesn’t accurately model the lifetime of the MVar, whichshould be garbage-collected once all threads that can access itfinish.

It makes MVars global objects, so our semantics aren’t veryabstract. We would like local communication to be local inour model.

25

Page 26: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

Restriction Operator

We introduce a restriction operator ν to our language of processes:

P,Q ::= a�= M| pure ()| P ‖ Q| 〈〉n | 〈v〉n| (ν n) P

Writing (ν n) P says that the MVar name n is only available inprocess P. Mentioning n outside P is not well-formed. We needthe following additional congruence equations:

(ν n) (ν m) P ≡ (ν m) (ν n) P(ν n)(P ‖ Q) ≡ P ‖ (ν n) Q (if n /∈ P)

26

Page 27: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

Better Semantics for newMVar

The rule for newMVar is much the same as before, but now weexplicitly restrict the MVar to M.

(newMVar v �= M) 7→ (ν n)(〈v〉n ‖ (pure n�= M))(n fresh)

We can always execute under a restriction:

P 7→ P ′

(ν n) P 7→ (ν n) P ′

Question

What happens when you put an MVar inside another MVar?

27

Page 28: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

Garbage Collection

If an MVar is no longer used, we just replace it with the do-nothingprocess:

(ν n) 〈〉n 7→ pure ()(ν n) 〈v〉n 7→ pure ()

Extra processes that have outlived their usefulness disappear:

pure () ‖ P 7→ P

28

Page 29: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

Process Algebra

Our language P is called a process algebra, and our method ofascribing semantics to P is called structural operational semantics.Neither are a focus of this course, but they are points whichintersect heavily with other courses at UNSW.

Process algebras and calculi of various kinds are covered ingreat detail in COMP6752 with Rob van Glabbeek, who is anexpert in this field.

Operational Semantics are a major part of the courseCOMP[39]161, which I develop and teach along with GabiKeller, who is the lecturer in charge.

If there’s time!

We can talk about CCS.

29

Page 30: COMP3151/9151 Foundations of Concurrency Lecture 8cs3151/17s2/lec/PDF/lecture08La.pdf · critical section solution (mutexes, semaphores, etc.) to ... See Algorithm 6.12 of the slides

Readers and Writers Haskell Operational Semantics

Bibliography

Simon Marlow

Parallel and Concurrent Programming in Haskell

O’Reilly, 2013

http://chimera.labs.oreilly.com/books/1230000000929

Simon Peyton Jones, Andrew Gordon and Sigbjorn Finne

Concurrent Haskell

POPL ’96

Association for Computer Machinery

http://microsoft.com/en-us/research/wp-content/uploads/1996/01/concurrent-haskell.pdf

Simon Marlow (Editor)

Haskell 2010 Language Report

https://www.haskell.org/onlinereport/haskell2010/

30