art of multiprocessor programming1 concurrent hashing companion slides for the art of multiprocessor...

98
Art of Multiprocessor Progr amming 1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified by Rajeev Alur for CIS640 University of Pennsylvania

Post on 21-Dec-2015

240 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

1

Concurrent Hashing

Companion slides forThe Art of Multiprocessor Programming

by Maurice Herlihy & Nir Shavit

Modified by Rajeev Alur for CIS640 University of Pennsylvania

Page 2: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

22

Linked Lists

• Ways to make highly-concurrent list-based Sets:– Fine-grained locks– Optimistic synchronization– Lazy synchronization– Lock-free synchronization

• What’s missing?

Page 3: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

3

Linear-Time Set Methods

• Problem is– add(), remove(), contains()– Take time linear in set size

• We want– Constant-time methods– (at least, on average)

Page 4: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

44

Hashing

• Hash function– h: items integers

• Uniformly distributed– Different item most likely have

different hash values

• Java hashCode() method

Page 5: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

55

Sequential Hash Map

0

1

2

3

16

9

h(k) = k mod 4h(k) = k mod 4

2 Items2 Items

buckets

Page 6: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

6

Add an Item

0

1

2

3

16

9

7

h(k) = k mod 4h(k) = k mod 4

3 Items3 Items

Page 7: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

77

Add Another: Collision

0

1

2

3

16 4

9

7

h(k) = k mod 4h(k) = k mod 4

4 Items4 Items

Page 8: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

88

More Collisions

0

1

2

3

16 4

9

7 15

h(k) = k mod 4h(k) = k mod 4

5 Items5 Items

Page 9: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

99

More Collisions

0

1

2

3

16 4

9

7 15

h(k) = k mod 4h(k) = k mod 4

5 Items5 ItemsProblem:

buckets getting too long

Page 10: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

1010

Resizing

0

1

2

3

16 4

9

7 15

4

5

6

7 Grow the array

5 Items5 Items

h(k) = k mod 8h(k) = k mod 8

Page 11: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

1111

5 Items5 Items

Resizing

0

1

2

3

16 4

9

7 15

4

5

6

7

h(k) = k mod 8h(k) = k mod 8

Adjust hash function

Page 12: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

1212

Resizing

0

1

2

3

16

9

7 15

h(4) = 0 mod 8

4

5

6

7

4

h(k) = k mod 8h(k) = k mod 8

Page 13: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

1313

Resizing

0

1

2

3

16

4

9

7 15

4

5

6

7

h(k) = k mod 8h(k) = k mod 8

h(4) = 4 mod 8

Page 14: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

1414

Resizing

0

1

2

3

16

4

9

7 15

4

5

6

7

h(k) = k mod 8h(k) = k mod 8

h(15) = 7 mod 8

Page 15: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

1515

Resizing

0

1

2

3

16

4

9

4

5

6

7

h(k) = k mod 8h(k) = k mod 8

h(15) = 7 mod 8

157

Page 16: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

1616

Hash Sets

• Implement a Set object– Collection of items, no duplicates– add(), remove(), contains()

methods– You know the drill …

Page 17: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

2525

No Brainer?

• We just saw a– Simple– Lock-free– Concurrent hash-based set

implementation

• What’s not to like?

Page 18: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

2626

No Brainer?

• We just saw a– Simple– Lock-free– Concurrent hash-based set

implementation

• What’s not to like?• We don’t know how to resize …

Page 19: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

2727

Is Resizing Necessary?

• Constant-time method calls require– Constant-length buckets– Table size proportional to set size– As set grows, must be able to resize

Page 20: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

2828

Set Method Mix

• Typical load– 90% contains()– 9% add ()– 1% remove()

• Growing is important• Shrinking not so much

Page 21: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

29

When to Resize?

• Many reasonable policies. Here’s one.

• Pick a threshold on num of items in a bucket

• Global threshold– When ≥ ¼ buckets exceed this value

• Bucket threshold– When any bucket exceeds this value

Page 22: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

30

Coarse-Grained Locking

• Good parts– Simple– Hard to mess up

• Bad parts– Sequential bottleneck

Page 23: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

31

Fine-grained Locking

0

1

2

3

4 8

9

7 11

17

Each lock associated with one bucket

Page 24: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

32

Resize ThisMake sure table reference didn’t change between resize decision and

lock acquisition

0

1

2

3

4 8

9

7 11

17

Acquire locks in ascending order

Page 25: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

33

Resize This

0

1

2

3

4 8

9

7 11

170

1

2

3

4

5

6

7

Allocate new super-sized

table

Page 26: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

34

Resize This

0

1

2

3

9

7

4 8

170

1

2

3

4

5

6

7

8

4

9 17

7

1111

Page 27: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

36

Resize This

0

1

2

3

0

1

2

3

4

5

6

7

8

4

9 17

7

11

Striped Locks: each lock now associated with two buckets

Page 28: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

37

Observations

• We grow the table, but not locks– Resizing lock array is tricky …

• We use sequential lists– Not LockFreeList lists– If we’re locking anyway, why pay?

Page 29: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

52

Fine-Grained Locks

• We can resize the table• But not the locks• Debatable whether method calls

are constant-time in presence of contention …

Page 30: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

53

Insight

• The contains() method– Does not modify any fields– Why should concurrent contains()

calls conflict?

Page 31: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

54

Read/Write Locks

public interface ReadWriteLock { Lock readLock(); Lock writeLock();}

Page 32: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

55

Read/Write Locks

public interface ReadWriteLock { Lock readLock(); Lock writeLock();}

Returns associated read

lock

Page 33: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

56

Read/Write Locks

public interface ReadWriteLock { Lock readLock(); Lock writeLock();}

Returns associated read

lockReturns

associated write lock

Page 34: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

57

Lock Safety Properties

• No thread may acquire the write lock– while any thread holds the write lock– or the read lock.

• No thread may acquire the read lock– while any thread holds the write lock.

• Concurrent read locks OK

Page 35: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

58

Read/Write Lock

• Satisfies safety properties– If readers > 0 then writer == false– If writer = true then readers == 0

• Liveness?– Lots of readers …– Writers locked out?

Page 36: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

59

FIFO R/W Lock

• As soon as a writer requests a lock• No more readers accepted• Current readers “drain” from lock• Writer gets in

Page 37: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

60

The Story So Far

• Resizing is the hard part• Fine-grained locks

– Striped locks cover a range (not resized)

• Read/Write locks– FIFO property needed

Page 38: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

61

Stop The World Resizing

• Resizing stops all concurrent operations

• What about an incremental resize? • Must avoid locking the table• A lock-free table + incremental

resizing?

Page 39: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

62

Lock-Free Resizing Problem

0

1

2

3

4 8

9

7 15

Page 40: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

63

Lock-Free Resizing Problem

0

1

2

3

4 8

9

7 15

12

Need to extend table

Page 41: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

64

4 12

Lock-Free Resizing Problem

0

1

2

3

8

9

7 15

4

5

6

7

4 12

Need to extend table

Page 42: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

65

Lock-Free Resizing Problem

0

1

2

3

84

9

7 15

4

5

6

7

12

4 12

Page 43: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

66

Lock-Free Resizing Problem

0

1

2

3

9

7 15

4

5

6

7

12

to remove and then add even a single item single location CAS not enough

4

84 12

We need a new idea…

Page 44: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

67

Don’t move the items

Move the buckets instead Keep all items in a single lock-free

list Buckets become “shortcut pointers”

into the list16 4 9 7 15

0123

Page 45: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

68

Recursive Split Ordering

0

0 4 2 6 1 5 3 7

Page 46: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

69

Recursive Split Ordering

0

1/2

1

0 4 2 6 1 5 3 7

Page 47: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

70

Recursive Split Ordering

0

1/2

1

1/4 3/4

2

3

0 4 2 6 1 5 3 7

Page 48: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

71

Recursive Split Ordering

0

1/2

1

1/4 3/4

2

3

0 4 2 6 1 5 3 7

List entries sorted in order that allows recursive splitting. How?

Page 49: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

7272

Recursive Split Ordering

0

0 4 2 6 1 5 3 7

Page 50: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

7373

Recursive Split Ordering

0

1

0 4 2 6 1 5 3 7

LSB 0 LSB 1

LSB = Least significant Bit

Page 51: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

7474

Recursive Split Ordering

0

12

3

0 4 2 6 1 5 3 7

LSB 00 LSB 10 LSB 01 LSB 11

Page 52: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

7575

Split-Order

• If the table size is 2i,– Bucket b contains keys k

• k = b (mod 2i)

– bucket index consists of key's i LSBs

Page 53: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

76

When Table Splits

• Some keys stay– b = k mod(2i+1)

• Some move– b+2i = k mod(2i+1)

• Determined by (i+1)st bit– Counting backwards

• Key must be accessible from both– Keys that will move must come later

Page 54: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

77

A Bit of Magic

0 4 2 6 1 5 3 7

Real keys:

Page 55: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

78

A Bit of Magic

0 4 2 6 1 5 3 7

Real keys:

0 1 2 3 4 5 6 7

Split-order:

Real key 1 is in the 4th location

Page 56: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

79

A Bit of Magic

0 4 2 6 1 5 3 7

Real keys:

0 1 2 3 4 5 6 7

Split-order:

000 100 010 110 001 101 011 111

000 001 010 011 100 101 110 111

Real key 1 is in 4th location

Page 57: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

80

A Bit of MagicReal keys:

Split-order:

000 100 010 110 001 101 011 111

000 001 010 011 100 101 110 111

Page 58: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

81

A Bit of MagicReal keys:

Split-order:

000 100 010 110 001 101 011 111

000 001 010 011 100 101 110 111

Just reverse the order of the key bits

Page 59: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

82

Split Ordered Hashing

0

12

3

0 4 2 6 1 5 3 7

000 001 010 011 100 101 110 111

Order according to reversed bits

Page 60: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

83

Parent Always Provides a Short Cut

0

12

3

0 4 2 6 1 5 3 7

search

Page 61: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

84

Sentinel Nodes

0

1

2

3

16 4 9 7 15

Problem: how to remove a node pointed by 2 sources using CAS

Page 62: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

85

Sentinel Nodes

0

1

2

3

16 4 9 7 153

Solution: use a Sentinel node for each bucket

0 1

Page 63: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

86

Sentinel vs Regular Keys

• Want sentinel key for i ordered – before all keys that hash to bucket i– after all keys that hash to bucket (i-1)

Page 64: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

87

Splitting a Bucket

• We can now split a bucket • In a lock-free manner• Using two CAS() calls ...

Page 65: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

88

Initialization of Buckets

0

1

16 4 9 7 150 1

Page 66: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

89

Initialization of Buckets

0

1

2

3

16 4 9 7 150 1

3

Need to initialize bucket 3 to split bucket 1

3 in list but not connected to bucket yet

Now 3 points to sentinel – bucket has been split

Page 67: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

90

Adding 10

0

1

2

3

16 4 9 3 70 1

2

10 = 2 mod 4

2

Must initialize bucket 2Then can add 10

Page 68: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

91

Recursive Initialization

0

1

2

3

8 120

7 = 3 mod 4To add 7 to the list

3

Must initialize bucket 3

Must initialize bucket 1

= 1 mod 2 1

Could be log n depthBut EXPECTED depth is constant

Page 69: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

92

Lock-Free List

int makeRegularKey(int key) { return reverse(key | 0x80000000);}int makeSentinelKey(int key) { return reverse(key);}

Page 70: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

93

Lock-Free List

int makeRegularKey(int key) { return reverse(key | 0x80000000);}int makeSentinelKey(int key) { return reverse(key);}

Regular key: set high-order bit to 1 and reverse

Page 71: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

94

Lock-Free List

int makeRegularKey(int key) { return reverse(key | 0x80000000);}int makeSentinelKey(int key) { return reverse(key);}

Sentinel key: simply reverse (high-order bit is

0)

Page 72: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

95

Main List

• Lock-Free List from earlier class• With some minor variations

Page 73: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

96

Lock-Free List

public class LockFreeList { public boolean add(Object object, int key) {...} public boolean remove(int k) {...} public boolean contains(int k) {...} public LockFreeList(LockFreeList parent, int key) {...};}

Page 74: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

97

Lock-Free List

public class LockFreeList { public boolean add(Object object, int key) {...} public boolean remove(int k) {...} public boolean contains(int k) {...} public LockFreeList(LockFreeList parent, int key) {...};}

Change: add takes key argument

Page 75: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

98

Lock-Free List

public class LockFreeList { public boolean add(Object object, int key) {...} public boolean remove(int k) {...} public boolean contains(int k) {...} public LockFreeList(LockFreeList parent, int key) {...};}

Inserts sentinel with key if not already present …

Page 76: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

99

Lock-Free List

public class LockFreeList { public boolean add(Object object, int key) {...} public boolean remove(int k) {...} public boolean contains(int k) {...} public LockFreeList(LockFreeList parent, int key) {...};}

… returns new list starting with sentinel (shares with

parent)

Page 77: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

100

Split-Ordered Set: Fields

public class SOSet { protected LockFreeList[] table; protected AtomicInteger tableSize; protected AtomicInteger setSize;

public SOSet(int capacity) { table = new LockFreeList[capacity]; table[0] = new LockFreeList(); tableSize = new AtomicInteger(2); setSize = new AtomicInteger(0); }

Page 78: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

101

Fields

public class SOSet { protected LockFreeList[] table; protected AtomicInteger tableSize; protected AtomicInteger setSize;

public SOSet(int capacity) { table = new LockFreeList[capacity]; table[0] = new LockFreeList(); tableSize = new AtomicInteger(2); setSize = new AtomicInteger(0); }

For simplicity treat table as big array …

Page 79: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

102

Fields

public class SOSet { protected LockFreeList[] table; protected AtomicInteger tableSize; protected AtomicInteger setSize;

public SOSet(int capacity) { table = new LockFreeList[capacity]; table[0] = new LockFreeList(); tableSize = new AtomicInteger(2); setSize = new AtomicInteger(0); }

In practice, want something that grows

dynamically

Page 80: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

103

Fields

public class SOSet { protected LockFreeList[] table; protected AtomicInteger tableSize; protected AtomicInteger setSize;

public SOSet(int capacity) { table = new LockFreeList[capacity]; table[0] = new LockFreeList(); tableSize = new AtomicInteger(2); setSize = new AtomicInteger(0); }

How much of table array are we actually using?

Page 81: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

104

Fields

public class SOSet { protected LockFreeList[] table; protected AtomicInteger tableSize; protected AtomicInteger setSize;

public SOSet(int capacity) { table = new LockFreeList[capacity]; table[0] = new LockFreeList(); tableSize = new AtomicInteger(2); setSize = new AtomicInteger(0); }

Track set size so we know when to resize

Page 82: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

105

Fields

public class SOSet { protected LockFreeList[] table; protected AtomicInteger tableSize; protected AtomicInteger setSize;

public SOSet(int capacity) { table = new LockFreeList[capacity]; table[0] = new LockFreeList(); tableSize = new AtomicInteger(1); setSize = new AtomicInteger(0); }

Initially use 1 bucket and size is zero

Page 83: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

106

Add() Method

public boolean add(Object object) { int hash = object.hashCode(); int bucket = hash % tableSize.get(); int key = makeRegularKey(hash); LockFreeList list = getBucketList(bucket); if (!list.add(object, key)) return false; resizeCheck(); return true;}

Page 84: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

107

Add() Method

public boolean add(Object object) { int hash = object.hashCode(); int bucket = hash % tableSize.get(); int key = makeRegularKey(hash); LockFreeList list = getBucketList(bucket); if (!list.add(object, key)) return false; resizeCheck(); return true;} Pick a bucket

Page 85: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

108

Add() Method

public boolean add(Object object) { int hash = object.hashCode(); int bucket = hash % tableSize.get(); int key = makeRegularKey(hash); LockFreeList list = getBucketList(bucket); if (!list.add(object, key)) return false; resizeCheck(); return true;}

Non-Sentinel split-ordered

key

Page 86: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

109

Add() Method

public boolean add(Object object) { int hash = object.hashCode(); int bucket = hash % tableSize.get(); int key = makeRegularKey(hash); LockFreeList list = getBucketList(bucket); if (!list.add(object, key)) return false; resizeCheck(); return true;}

Get pointer to bucket’s sentinel, initializing if

necessary

Page 87: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

110

Add() Method

public boolean add(Object object) { int hash = object.hashCode(); int bucket = hash % tableSize.get(); int key = makeRegularKey(hash); LockFreeList list = getBucketList(bucket); if (!list.add(object, key)) return false; resizeCheck(); return true;}

Call bucket’s add() method with reversed key

Page 88: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

111

Add() Method

public boolean add(Object object) { int hash = object.hashCode(); int bucket = hash % tableSize.get(); int key = makeRegularKey(hash); LockFreeList list = getBucketList(bucket); if (!list.add(object, key)) return false; resizeCheck(); return true;}

No change? We’re done.

Page 89: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

112

Add() Method

public boolean add(Object object) { int hash = object.hashCode(); int bucket = hash % tableSize.get(); int key = makeRegularKey(hash); LockFreeList list = getBucketList(bucket); if (!list.add(object, key)) return false; resizeCheck(); return true;}

Time to resize?

Page 90: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

113

Resize

• Divide set size by total number of buckets

• If quotient exceeds threshold– Double tableSize field– Up to fixed limit

Page 91: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

114

Initialize Buckets

• Buckets originally null• If you find one, initialize it• Go to bucket’s parent

– Earlier nearby bucket– Recursively initialize if necessary

• Constant expected work

Page 92: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

115

Recall: Recursive Initialization

0

1

2

3

8 120

7 = 3 mod 4To add 7 to the list

3

Must initialize bucket 3

Must initialize bucket 1

= 1 mod 2 1

Could be log n depthBut EXPECTED depth is constant

Page 93: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

116

Initialize Bucket

void initializeBucket(int bucket) { int parent = getParent(bucket); if (table[parent] == null) initializeBucket(parent); int key = makeSentinelKey(bucket); LockFreeList list = new LockFreeList(table[parent], key); }

Page 94: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

117

Initialize Bucket

void initializeBucket(int bucket) { int parent = getParent(bucket); if (table[parent] == null) initializeBucket(parent); int key = makeSentinelKey(bucket); LockFreeList list = new LockFreeList(table[parent], key); } Find parent, recursively

initialize if needed

Page 95: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

118

Initialize Bucket

void initializeBucket(int bucket) { int parent = getParent(bucket); if (table[parent] == null) initializeBucket(parent); int key = makeSentinelKey(bucket); LockFreeList list = new LockFreeList(table[parent], key); } Prepare key for new

sentinel

Page 96: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

119

Initialize Bucket

void initializeBucket(int bucket) { int parent = getParent(bucket); if (table[parent] == null) initializeBucket(parent); int key = makeSentinelKey(bucket); LockFreeList list = new LockFreeList(table[parent], key); }

Insert sentinel if not present, and get back reference to rest

of list

Page 97: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

120

Correctness• Linearizable concurrent set

implementation• Theorem: O(1) expected time

– No more than O(1) items expected between two dummy nodes on average

– Lazy initialization causes at most O(1) expected recursion depth in initializeBucket()

Page 98: Art of Multiprocessor Programming1 Concurrent Hashing Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified

Art of Multiprocessor Programming

121

Summary

• Concurrent resizing is tricky• Lock-based

– Fine-grained– Read/write locks– Optimistic

• Lock-free– Builds on lock-free list