57
@gfraiteur Surmounting complexity by raising abstraction Multithreading Design Patterns Gaël Fraiteur PostSharp Technologies Founder & Principal Engineer

Multithreading Design Patterns

Embed Size (px)

DESCRIPTION

Gael Fraiteur argues that multithreaded programming needs to be addressed at the right level of abstraction, with design patterns like Actor, Immutable, Freezable, Thread Affine, Reader-Writer-Synchronized. Design patterns form a language and serve as a model against which code can be expressed. Compilers must support design patterns to allow code to be deterministically validated against the model, and of course to generate the low-level instructions that would be otherwise written manually.

Citation preview

Page 1: Multithreading Design Patterns

@gfraiteur

Surmounting complexity by raising abstraction

Multithreading Design Patterns

Gaël Fraiteur

PostSharp TechnologiesFounder & Principal Engineer

Page 2: Multithreading Design Patterns

@gfraiteur

Hello!

My name is GAEL.

No, I don’t thinkmy accent is funny.

my twitter

Page 3: Multithreading Design Patterns

@gfraiteur

My commitment to you:to seed a vision, not to sell a tool.

Page 4: Multithreading Design Patterns

@gfraiteur

The vision:Code at the right level of abstraction,with compiler-supported design patterns

Page 5: Multithreading Design Patterns

@gfraiteur

back in

1951

Page 6: Multithreading Design Patterns

@gfraiteur

hardware was fun but quite simple to use

Page 7: Multithreading Design Patterns

@gfraiteur

Univac Assembly Language

Page 8: Multithreading Design Patterns

@gfraiteur

FORTRAN (1955)• 1955 - FORTRAN I

• Global Variables

• Arrays

• 1958 - FORTRAN II

• Procedural Programming(no recursion)

• Modules

Page 9: Multithreading Design Patterns

@gfraiteur

COBOL (1959)• Data Structures

Page 10: Multithreading Design Patterns

@gfraiteur

LISP (1959)• Variable Scopes (Stack)

• Garbage Collection

Page 11: Multithreading Design Patterns

@gfraiteur

“The new invention caught quickly, no wonder, programs computing nuclear power reactor parameters took now

HOURS INSTEAD OF WEEKS

to write, and required much

LESS PROGRAMMING SKILL

Page 12: Multithreading Design Patterns

@gfraiteur

1. The Memory Management Revolution

2. Models and Patterns3. Defining Threading Models

4. Designing with Threading Models

5. A Few Threading Models

6. Q&A

7. Summary

Section

Page 13: Multithreading Design Patterns

@gfraiteur

How do programming languagesincrease productivity?

Page 14: Multithreading Design Patterns

@gfraiteur

What you may think the compiler does for you.

Code Validation

Instruction Generation

Page 15: Multithreading Design Patterns

@gfraiteur

Compilers translate codeFROM HIGH TO LOW ABSTRACTION language

Page 16: Multithreading Design Patterns

@gfraiteur

Languages let us express ourselves against a model

Thing Concept Word

Model Language

∞ 1

World

abstracted into expressed with

∞ ∞

1 1

1

1 1

abstracted into expressed with

Page 17: Multithreading Design Patterns

@gfraiteur

Good Models are Easy• Allow for succinct expression of intent (semantics), with

less focus on implementation details

• less work

• fewer things to think about

• Allow for extensive validation of source code against the model

• early detection of errors

• Allow for better locality and separation of concerns

• “everything is related to everything” no more

• Are deterministic

• no random error

Page 18: Multithreading Design Patterns

@gfraiteur

Good Models are Friendly• to human mind structure

• cope with limited human cognitive abilities

• to social organization

• cope with skillset differences, division of labor, time dimension, changes in requirements

Page 19: Multithreading Design Patterns

@gfraiteur

The Classic Programming ModelQuality Realization

Succinct semantics • Concept of subroutine• Unified concept of variable

(global, local, parameters, fields)

Validation • Syntactic (spelling)• Semantic (type analysis) • Advanced (data flow analysis)

Locality • Information hiding (member visibility)• Modularity

Determinism • Total (uninterrupted single-threaded program)

Page 20: Multithreading Design Patterns

@gfraiteur

1. The Memory Management Revolution

2. Models and Patterns

3. Defining Threading Models

4. Designing with Threading Models

5. A Few Threading Models

6. Q&A

7. Summary

Section

Page 21: Multithreading Design Patterns

@gfraiteur

Why we need threading models• Multithreading is way too hard – today

• Too many things to think about

• Too many side effects

• Random data races

• Your colleagues won’t get smarter

• Increased demand – end of free lunch

Page 22: Multithreading Design Patterns

@gfraiteur

Page 23: Multithreading Design Patterns

@gfraiteur

The Root of All Evil

Access to Shared Mutable State• Memory ordering

• Atomicity / transactions

• Typical damage: data races

• Corruption of data structures

• Invalid states

Page 24: Multithreading Design Patterns

@gfraiteur

Locks alone are not the solution

Page 25: Multithreading Design Patterns

@gfraiteur

Page 26: Multithreading Design Patterns

@gfraiteur

Locks alone are not the solution• Easy to forget

• Difficult to test

• Deadlocks

Page 27: Multithreading Design Patterns

@gfraiteur

"Problems cannot be solved by the same level of thinking that created them."

(and you’re not a man if you haven’t cited Albert Einstein)

Page 28: Multithreading Design Patterns

@gfraiteur

Threading Models

Reader-Writer

Sync’ed

PessimisticTransactions

Lock-Based

Lock-Free

OptimisticTransactio

nsTransactional

Avoid Mutable State

Thread Exclusive

Immutable

Actor

Avoid Shared Mutable State

Avoid Shared State

Page 29: Multithreading Design Patterns

@gfraiteur

• Named solution

• Best practice

• Documented

• Abstraction

• Automation

• Validation

• Determinism

Threading Models are…

Models Design Patterns

Page 30: Multithreading Design Patterns

@gfraiteur

1. The Memory Management Revolution

2. Models and Patterns

3. Defining Threading Models

4. Designing with Threading Models

5. A Few Threading Models

6. Q&A

7. Summary

Section

Page 31: Multithreading Design Patterns

@gfraiteur

Golden rule: all shared state must be thread-safe.

Page 32: Multithreading Design Patterns

@gfraiteur

Assign threading models to types

1. Every class must be assigned a threading model.

2. Define aggregates with appropriate granularity.

1.

Page 33: Multithreading Design Patterns

@gfraiteur

Product

Invoice

Party

Store

Invoice InvoiceLine

Product

-lines

1

-invoice

*

-product *

1

Party

-invoices1

-customer*

ProductPart-parts

1

-product

*

Address

-addresses

1*

StockItem

Store

-items 1

-store *

*

-part1

reader-writer-synchronized

reader-writer-synchronizedreader-writer-

synchronized

actor

Page 34: Multithreading Design Patterns

@gfraiteur

Ensure only thread-safe types are shared

1. Arguments of cross-thread methods

2. All static fields must be read-only and of thread-safe type.

2.

Page 35: Multithreading Design Patterns

@gfraiteur

1. The Memory Management Revolution

2. Models and Patterns

3. Defining Threading Models

4. Designing with Threading Models

5. A Few Threading Models6. Q&A

7. Summary

Section

Page 36: Multithreading Design Patterns

@gfraiteur

Immutable PatternNever changed after creation.Make a copy if you want to modify it.

Issue: multi-step object initialization (e.g. deserialization)

Page 37: Multithreading Design Patterns

@gfraiteur

Freezable Pattern1. Implement interface IFreezable

Freeze() must propagate tochildren objects.

2. Before any non-const method, throw exception if object is frozen.

3. Call the Freeze method after any initialization.

Page 38: Multithreading Design Patterns

@gfraiteur

Thread ExclusivePromises never to be involvedwith multithreading. Ever.

Page 39: Multithreading Design Patterns

@gfraiteur

Thread Exclusivity Strategies• Exclusivity Policies:

• Thread Affinity (e.g. GUI objects)

• Instance-Level Exclusivity (e.g. most .NET objects)

• Type-Level Exclusivity

• Concurrency Behavior:• Fail with exception

• Wait with a lock

Page 40: Multithreading Design Patterns

@gfraiteur

Implementing Thread Affine Objects

• Remember current thread in constructor

• Verify current thread in any public method

• Prevent field access from outside current instance

• Only private/protected fields

• Only accessed in “this.field”

Page 41: Multithreading Design Patterns

@gfraiteur

Implementing Thread Excluse Objects

• Acquire lock before any public method

• Wait/throw if it cannot be acquired

• Prevent field access from outside current instance

• Only private/protected fields

• Only accessed in “this.field”

• Note: “Throw” behavior is non-deterministic

Page 42: Multithreading Design Patterns

@gfraiteur

Stricter coding constraints increase code verifiability.

Page 43: Multithreading Design Patterns

@gfraiteur

Lab: Checking Thread Exclusivity

Page 44: Multithreading Design Patterns

@gfraiteur

Actor ModelBound to a single thread(at a time)

Page 45: Multithreading Design Patterns

@gfraiteur

MessageQueue

PrivateMutable

State

SingleWorker

Actors:No Mutable Shared State

Page 46: Multithreading Design Patterns

@gfraiteur

Composing Actors

Page 47: Multithreading Design Patterns

@gfraiteur

Actor Sequence Diagram

Object1 Object2 Object3

Request1 Request2

Response1

Response2

Wait in message queue

Page 48: Multithreading Design Patterns

@gfraiteur

• with compiler support:

• Erlang,

• F# Mailbox

• PostSharp

• without compiler support:

• NAct

• ActorFX

Actor implementations

Page 49: Multithreading Design Patterns

@gfraiteur

Verifying the Actor Model• Public methods will be made async

• Parameters and return values of public methods must be thread-safe

• Methods with return value must be async

• Prevent field access from outside current instance

• Only private/protected fields

• Only accessed in “this.field”

Page 50: Multithreading Design Patterns

@gfraiteur

Lab: Implementing Actors

Page 51: Multithreading Design Patterns

@gfraiteur

• Performance• Theoretical Latency: min 20 ns

(L3 double-trip)

• Practical throughput (ring buffer): max 6 MT/s per core

• Difficult to write without proper compiler support

• Reentrance issues with waiting points (await)

• Race free (no shared mutable state)

• Lock free (no waiting, no deadlock)

• Scales across processes, machines

Actors

Benefits Limitations

Page 52: Multithreading Design Patterns

@gfraiteur

Reader-Writer SynchronizedEverybody can read unless someone writes.

Page 53: Multithreading Design Patterns

@gfraiteur

Reader-Writer Synchronized• 1 lock per [group of] objects

• e.g. invoice and invoice lines share the same lock

• Most public methods require locks:

Method Required Lock Level

Reads 1 piece of state None

Reads 2 pieces of state Read

Writes 1 piece of state Write

Reads large amount of state, then writes state

Upgradeable Read, then Write

Page 54: Multithreading Design Patterns

@gfraiteur

Lab: Implementing RWS

Page 55: Multithreading Design Patterns

@gfraiteur

Transactions• Isolate shared state into thread-specific storage

• Commit/Rollback semantics

• Platform ensures ACID properties:

• Atomicity, Consistency, Isolation, (Durability)

• Type of concurrency policies

• Pessimistic (lock-based: several “isolation levels” available)

• Optimistic (lock-free, retry-based)

As far as I'm concerned, I prefer silent vice to ostentatious virtue. Albert Einstein “

Page 56: Multithreading Design Patterns

@gfraiteur

Q&AGael [email protected]@gfraiteur

Page 57: Multithreading Design Patterns

@gfraiteur

Summary• Repeat the memory

management success with the multicore issue.

• Models decrease complexity to a cognitively bearable level.

• We need compilers that allow us to use our own modelsand patterns.

BETTER SOFTWARE THROUGH SIMPLER CODE