Top Banner
Low level concurrency Reinventing vehicle Olena Syrota
48

Low-level concurrency (reinvent vehicle)

Jul 27, 2015

Download

Education

Olena Syrota
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Low-level concurrency (reinvent vehicle)

Low level concurrency

Reinventing vehicle

Olena Syrota

Page 2: Low-level concurrency (reinvent vehicle)

Motivation• Where is computer science in software

engineering?• Not technologies• Real computer science• Algorithms• Algorithm’s properties

Page 3: Low-level concurrency (reinvent vehicle)

Literature

Page 4: Low-level concurrency (reinvent vehicle)

Low level concurrencyMutex

Page 5: Low-level concurrency (reinvent vehicle)

Mutual Exclusion (mutex)• Q: How to implement mutex in software?• A: Using some “lock” library

Page 6: Low-level concurrency (reinvent vehicle)

Mutex - back to computer science

Page 7: Low-level concurrency (reinvent vehicle)

• Let’s imagine you have no Lock mechanism• You have to invent it!!!

Page 8: Low-level concurrency (reinvent vehicle)

Reinventing first wheel

Page 9: Low-level concurrency (reinvent vehicle)

Scene

• Alice and Bob are neighbors• They share a yard• Alice has a cat• Bob has a dog

• Shared yard – is shared resource

We have to invent protocol for mutual exclusive access to resource (mutual exclusion)

Page 10: Low-level concurrency (reinvent vehicle)

Protocol 0 • Alice and Bob never release the pets

Page 11: Low-level concurrency (reinvent vehicle)

Properties• Mutual exclusion. Resource is not used at the same

time

Page 12: Low-level concurrency (reinvent vehicle)

Protocol 1 - asking

• Shouting, Knocking on the door, Cell phone

• Protocol: • Ask if I can release the pet

• Good• Comparing with protocol 0 pets can

reach the yard

• Bad:• If Alice is knocking to the Bob’s door

(shouting, dialing) and• Bob is not at home or does not hear,

turned off phone etc

Two problems

• Message can be lost• if other side is

unreachable at the moment it will never know about our intention

• Protocol requires interaction with other side. • Other side can be

unreachable. • When translating to

computer “language” we will spend time of other side to solve task. This is overhead.

Page 13: Low-level concurrency (reinvent vehicle)

Properties - waiting• Waiting• Can we reduce time of waiting, and wait only when

resource is busy but not when counterpart is not available?

• We need to persist intention to lock shared resource to reduce waiting

Page 14: Low-level concurrency (reinvent vehicle)

Persistent communication• Mutual exclusion requires persistent

communication

Page 15: Low-level concurrency (reinvent vehicle)

Protocol 2 - cans

Bob Alice

Yard

Page 16: Low-level concurrency (reinvent vehicle)

Protocol 2 - cans

Cans (one or several) are on the Bob’s windowsill

• The protocol is:• Alice

• Alice yanks the string to knock over of the cans

• When Bob notices that can is knocked over, he resets the can

• Alice release the cat

• Bob• Bob release the dog

whenever he needs it

• Good:• Alice’s intension is “persistent”

• Bad:• Bob can be out of home• Bob can notice that can is

knocked over too late• Not-fair protocol

Problem

This protocol divert counterpart and we are still waiting

Page 17: Low-level concurrency (reinvent vehicle)

17

Bob Alice

Yard

Protocol 3 – flags

Page 18: Low-level concurrency (reinvent vehicle)

Protocol 3 – flagsBob

1. He raises his flag.2. Look at Alice’s flag. If

is lowered, he unleashes his dog.

3. When his dog comes back, he lowers his flag.

Alice

1. She raises her flag.2. Look at Bob’s flag. If is

lowered, she unleashes her cat.

3. When her cat comes back, she lowers her flag.

What is wrong? If Alice and Bob will do steps simultaneously the pets will never reach the yard. Livelock.

Page 19: Low-level concurrency (reinvent vehicle)

Propeties - livelock• Livelock. Livelocked threads are unable to make

further progress. However, the threads are not blocked — they are simply too busy responding to each other to resume work.

Page 20: Low-level concurrency (reinvent vehicle)

Protocol 3 – flags. With priority.Bob (gives way to Alice to avoid live-lock)

1. He raises his flag.2. While Alice’s flag is raised

1. Bob lowers his flag2. Bob waits until Alice’s flag is

lowered3. Bob raises his flag

3. As soon as his flag is raised and hers is down, he unleashes his dog.

4. When his dog comes back, he lowers his flag.

Alice

1. She raises her flag.2. When Bob’s flag is

lowered, she unleashes her cat.

3. When her cat comes back, she lowers her flag.

This is not fair algorithm since it give priority to Alice. Bob’s dog can

wait forever with this approach. Starvation.

What is wrong?

Page 21: Low-level concurrency (reinvent vehicle)

Code itboolean flag[];flag[0] = false; flag[1] = false;

Bob:flag[1] = true;if (flag[0] == true) { flag[1] = false; while (flag[0] == true) { } flag[1] = true;}// critical section...flag[1] = false;// remainder section

Alice:flag[0] = true;while (flag[1] == true) {}

// critical section...flag[0] = false;// remainder section

Page 22: Low-level concurrency (reinvent vehicle)

Properties - starvation• Starvation - a thread is unable to gain regular

access to shared resources and is unable to make progress. This happens when shared resources are made unavailable for long periods by "greedy" threads

Page 23: Low-level concurrency (reinvent vehicle)

Dekker’s algorithm• Last slides we presented non-fair algorithm• Fair variant is called Dekker’s algorithm• priority is turned every time when lock needed

• Authors of Dekker’s algorithm: Dekker, Dijkstra

• It allows two threads to share a single-use resource without conflict, using only shared memory for communication

Page 24: Low-level concurrency (reinvent vehicle)

Dekker’s algorithms(var “turn” introduced to change priority)boolean flag[];flag[0] = false; flag[1] = false; int turn = 0 // or 1

P0:flag[0] = true;while (flag[1] == true) { if (turn ≠ 0) { flag[0] = false; while (turn ≠ 0) { // busy wait } flag[0] = true; }}// critical section...turn = 1;flag[0] = false;// remainder section

P1:flag[1] = true;while (flag[0] == true) { if (turn ≠ 1) { flag[1] = false; while (turn ≠ 1) { // busy wait } flag[1] = true; }}// critical section...turn = 0;flag[1] = false;// remainder section

Page 25: Low-level concurrency (reinvent vehicle)

Properties of good lock-protocol• Mutual Exclusion

• Resource is not used at the same time

• Deadlock freedom• if one pet wants to enter the yard, then it eventually succeeds • if both pets want to enter the yard, then eventually at least one of them

succeeds

• Starvation freedom• if a pet wants to enter the yard, will it eventually succeed?• If resource was locked, will it be locked out?

• Livelock-freedom• livelock is a special case of starvation. This property is proved via resource

starvation

• Waiting• Imagine that Alice raises her flag, and is then suddenly stricken with

appendicitis. The protocol states that Bob (and his dog) must wait for Alice to lower her flag. If Alice is delayed, then Bob is also delayed

Page 26: Low-level concurrency (reinvent vehicle)

Deadlock• For API users deadlock is:• Deadlock describes a situation where two or more threads are

blocked forever, waiting for each other.• Deadlock is easy to understand with 2 threads and 2+ shared

resources

• But we are protocol developers (not API users). We need deadlock-freedom property for lock

• The API developers meaning of deadlock is: If some thread attempts to acquire the lock, then some thread will succeed in acquiring the lock. If thread A calls lock() but never acquires the lock, then other threads must be completing an infinite number of critical sections

Page 27: Low-level concurrency (reinvent vehicle)

Summary

Property/Protocol “Flags” With priority

Dekker’s

Mutual Exclusion + +

Deadlock freedom + +

Starvation freedom - +

Starvation free -> deadlock free

Page 28: Low-level concurrency (reinvent vehicle)

• Mutual exclusion between two threads can be solved (however imperfectly) using only two one-bit variables, each of which can be written by one thread and read by the other.

Page 29: Low-level concurrency (reinvent vehicle)

Concurrent prime-numbers

// shared by all threads1 Counter counter = new Counter(1);

// next function is executed in parallel2 void primePrint() { 3 long i = 0;4 long limit = power(10, 10);5 while (i < limit) {6 i = counter.getAndIncrement(); 7 if (isPrime(i))8 print(i);9 }10 }

Page 30: Low-level concurrency (reinvent vehicle)

class Counter {

private int cntr;

private Lock mutex;

public int getAndIncrement() {

mutex.lock();

try {

cntr++; // body

} finally {

mutex.unlock();

}

}

}

Page 31: Low-level concurrency (reinvent vehicle)

Other algorithms for reinventing vehicles

Page 32: Low-level concurrency (reinvent vehicle)

2 threads cases

Page 33: Low-level concurrency (reinvent vehicle)

LockOne algorithm• Only for 2 threads• Thread Ids: 0, 1• i = ThreadID.get()• Other thread’s id j=1-i

Page 34: Low-level concurrency (reinvent vehicle)

LockOne algorithm (2-Thread Solution)

1 class LockOne implements Lock { // thread-local index, 0 or 12 private boolean[] flag = new boolean[2];

4 public void lock() {5 int i = ThreadID.get();6 int j = 1 - i;7 flag[i] = true;8 while (flag[j]) {} // wait9 }

10 public void unlock() {11 int i = ThreadID.get();12 flag[i] = false;13 }14 }

Lock and unlock functions can be

called concurrently and race condition

can occur

Page 35: Low-level concurrency (reinvent vehicle)

LockOne algorithm (2-Thread Solution)

1 class LockOne implements Lock { // thread-local index, 0 or 12 private boolean[] flag = new boolean[2];

4 public void lock() {5 int i = ThreadID.get();6 int j = 1 - i;7 flag[i] = true;8 while (flag[j]) {} // wait9 }

10 public void unlock() {11 int i = ThreadID.get();12 flag[i] = false;13 }14 }

Thread 0

Two threads call lock/unlocksimultaneously

Thread 1

Page 36: Low-level concurrency (reinvent vehicle)

Properties of LockOne

• Mutual exclusion• Deadlock free

• If writeA(flag[A] = true) and writeB(flag[B] = true) events occur before readA(flag[B]) and readB(flag[A]) events, then both threads wait forever.

• LockOne has an interesting property: if one thread runs before the other, no deadlock occurs, and all is well.

1 class LockOne implements Lock {

// thread-local index, 0 or 1

2 private boolean[] flag = new boolean[2];

4 public void lock() {

5 int i = ThreadID.get();

6 int j = 1 - i;

7 flag[i] = true;

8 while (flag[j]) {} // wait

9 }

10 public void unlock() {

11 int i = ThreadID.get();

12 flag[i] = false;

13 }

14 }

Page 37: Low-level concurrency (reinvent vehicle)

LockTwo1 class LockTwo implements Lock {

2 private volatile int victim;

3 public void lock() {

4 int i = ThreadID.get();

5 victim = i; // let the other go first

6 while (victim == i) {} // wait

7 }

8 public void unlock() {}

9 }

Page 38: Low-level concurrency (reinvent vehicle)

LockTwo

1 class LockTwo implements Lock {

2 private volatile int victim;

3 public void lock() {

4 int i = ThreadID.get();

5 victim = i; // let the other go first

6 while (victim == i) {} // wait

7 }

8 public void unlock() {}

9 }

Thread 0

One thread runs completely before other

Thread 1

Page 39: Low-level concurrency (reinvent vehicle)

LockTwo

1 class LockTwo implements Lock {

2 private volatile int victim;

3 public void lock() {

4 int i = ThreadID.get();

5 victim = i; // let the other go first

6 while (victim == i) {} // wait

7 }

8 public void unlock() {}

9 }

• Mutual exclusion• Deadlock free

• it deadlocks if one thread runs completely before the other

• LockTwo has an interesting property: if the threads run concurrently, the lock() method succeeds

Page 40: Low-level concurrency (reinvent vehicle)

Peterson Lock1 class Peterson implements Lock {

2 // thread-local index, 0 or 1

3 private volatile boolean[] flag = new boolean[2];

4 private volatile int victim;

5 public void lock() {

6 int i = ThreadID.get();

7 int j = 1 - i;

8 flag[i] = true; // I’m interested

9 victim = i; // you go first

10 while (flag[j] && victim == i) {}; // wait

11 }

12 public void unlock() {

13 int i = ThreadID.get();

14 flag[i] = false; // I’m not interested

15 }

16 }

Page 41: Low-level concurrency (reinvent vehicle)

• When implementing in Java use volatile and AtomicIntegerArray (java.util.concurrent.atomic)

Page 42: Low-level concurrency (reinvent vehicle)

Properties of Peterson algorithm• Mutual exclusion• Starvation free• Deadlock free

Page 43: Low-level concurrency (reinvent vehicle)

N threads cases

Page 44: Low-level concurrency (reinvent vehicle)

Lamport’s Bakery Algorithm• first-come-first-served

• When a thread wants to enter its critical section, it sets a flag, and takes a number greater than the numbers of all other threads.

• When all lower numbers have been served, the thread can enter.

• At leaving its critical section, the thread resets its flag.

Page 45: Low-level concurrency (reinvent vehicle)

Lamport’s Bakery Algorithm1 class Bakery implements Lock {2 boolean[] flag;3 Label[] label;4 public Bakery (int n) {5 flag = new boolean[n];6 label = new Label[n];7 for (int i = 0; i < n; i++) {8 flag[i] = false; label[i] = 0;9 }10 }11 public void lock() {12 int i = ThreadID.get();13 flag[i] = true;14 label[i] = max(label[0], ...,label[n-1]) + 1;15 while (( k != i)(flag[k] && (label[k],k) << (label[i],i))) {};16 }17 public void unlock() {18 flag[ThreadID.get()] = false;19 }20 }

flag[A] - whether A wants toenter the critical sectionlabel[A] - indicates the thread’srelative order when entering the bakery<< lexicographical order

(label[i], i) << (label[j], j)if and only if

label[i] < label[j] or label[i] = label[j] and i < j

Page 46: Low-level concurrency (reinvent vehicle)

Properties of Bakery Algorithm• Mutual exclusion• Starvation free• Deadlock free• First-come-first-served

• Note that any algorithm that is both deadlock-free and first-come-first-served is also starvation-free.

Page 47: Low-level concurrency (reinvent vehicle)

We considered• We considered• Dekker’s• Peterson• Lamport’s Bakery

• We did not considered compareAndSet approach, atomics, STM, actors

Page 48: Low-level concurrency (reinvent vehicle)

Homework• Select lock library (select your favorite lock

algorithm)• Remember of reordering. Use volatile or Atomic for

shared variable.

• Implement use case (concurrent stack, concurrent prime-numbers, etc)