Lock-Free Algorithms
Present by PanPan
Multi-Thread Programming Problem
a = a + 1
Read a
Calculate a + 1
Save a + 1
Thread A
Read a
Save a + 1
Calculate a + 1
Thread B
Read a
Save a + 1
Calculate a + 1
Time
Multi-Thread Programming Solution
●Blocking
○Mutex
○Critical Section
●Non-Blocking
○Wait-Free
○Lock-Free
○Obstruction-Free
●Local
○No Shared Data
Dead Lock
void FunctionA()
Enter Critical Section A
Leave Critical Section A
Leave Critical Section B
Enter Critical Section B
void FunctionB()
Enter Critical Section A
Leave Critical Section B
Leave Critical Section A
Enter Critical Section B
Do Something
Do Something
Do Something
Time
Call FunctionA
Return
(Or Close)
Do Something
Dead Lock
Dead Lock
Dead Lock
Dead Lock
What is Lock-Free?
A lock-free data structure is one that doesn't
use any mutex locks. The implication is that
multiple threads can access the data structure
concurrently without race conditions or data
corruption, even though there are no locks —
people would give you funny looks if you
suggested that std::list was a lock-free data
structure, even though it is unlikely that there
are any locks used in the implementation. [1]
Non-Blocking
Obstruction-Free
Lock-Free
Wait-Free
[1] http://www.justsoftwaresolutions.co.uk/threading/non_blocking_lock_free_and_wait_free.html
Advantages and Disadvantages
●No "Lock" (Also No Dead Lock)
●Better Performance
●Hard to Implement
Main Concept
●Use Atom Operation to Modify
Critical Data
●Enter a Spin State When Atom
Operation Fail
Atom Operation
Success?
Finish
No
Yes
Compare and Swap
bool CAS(uint32* pointer, uint32 old_value, uint32 new_value)
{
if (*pointer == old_value)
{
*pointer = new_value;
return true;
}
return false;
}
InterlockedCompareExchange - Windows API
Other Atom Operation
●CAS2 - Compare and Swap 2
●CASN - Compare and Swap N
●DCAS - Double Compare Swap
●MCAS - Multiword Compare and Swap
●LL/SC - Load Linked / Store Conditional
Example - Stack
struct Node
{
volatile Node* next;
};
class Stack
{
volatile Node* head;
public:
void Push(Node* node);
void Pop();
Stack() : head(0) {}
};
void Stack::Push(Node* node)
{
while (true)
{
node->next = head;
if (CAS(&head, node->next, node))
break;
}
}
void Stack::Pop()
{
while (true)
{
node* old_head = head;
if (head == 0)
break;
node* next_node = old_head->next;
if (CAS(&head, old_head, next_node))
break;
}
}
Something Wrong
ABA Problem
Thread A
A
B
C
A
B
C
Head
Pop
Thread B
A
B
C
Pop
C
A
Push
Head
Head
Head
node* old_head = head;
if (head == 0)
break;
node* next_node = old_head->next;
if (CAS(&head, old_head, next_node))
break;
Solute ABA Problem
●LL/SC
○It would return false when target have
done a "write" action
●CAS2
○Add a versioned value
Example - Stack(fix Pop)
void Stack::Pop()
{
while (true)
{
node* old_head = head;
int old_version = version;
if (head == 0)
break;
node* next_node = old_head->next;
if (CAS2(&head, old_head, old_version, next_node, old_version + 1))
break;
}
}
class Stack
{
volatile Node* head;
volatile int version;
public:
void Push(Node* node);
void Pop();
Stack() : head(0), version(0) {}
};
Add Version
Check Version
Summary
●Lock-Free has Better Performance Than Blocking
●Lock-Free has no "Lock"
●Lock-Free is Hard To Implement
●Lock-Free's Spirit - Atom Operation
●Lock-Free's Trap - ABA Problem
Notes and References
●Toby Jones - Lock-Free Algorithms(Game Programming
Gems 6)
●Jean-Francois Dube - Efficient and Scalable Multi-Core
Programming(Game Programming Gems 8)
●Zhou Wei Ming - Multi-core Computing and Programming
Any Questions?
Thanks for your attention
By PanPan
2010-06-29

Lock free algorithms

  • 1.
  • 2.
    Multi-Thread Programming Problem a= a + 1 Read a Calculate a + 1 Save a + 1 Thread A Read a Save a + 1 Calculate a + 1 Thread B Read a Save a + 1 Calculate a + 1 Time
  • 3.
    Multi-Thread Programming Solution ●Blocking ○Mutex ○CriticalSection ●Non-Blocking ○Wait-Free ○Lock-Free ○Obstruction-Free ●Local ○No Shared Data
  • 4.
    Dead Lock void FunctionA() EnterCritical Section A Leave Critical Section A Leave Critical Section B Enter Critical Section B void FunctionB() Enter Critical Section A Leave Critical Section B Leave Critical Section A Enter Critical Section B Do Something Do Something Do Something Time Call FunctionA Return (Or Close) Do Something Dead Lock Dead Lock Dead Lock Dead Lock
  • 5.
    What is Lock-Free? Alock-free data structure is one that doesn't use any mutex locks. The implication is that multiple threads can access the data structure concurrently without race conditions or data corruption, even though there are no locks — people would give you funny looks if you suggested that std::list was a lock-free data structure, even though it is unlikely that there are any locks used in the implementation. [1] Non-Blocking Obstruction-Free Lock-Free Wait-Free [1] http://www.justsoftwaresolutions.co.uk/threading/non_blocking_lock_free_and_wait_free.html
  • 6.
    Advantages and Disadvantages ●No"Lock" (Also No Dead Lock) ●Better Performance ●Hard to Implement
  • 7.
    Main Concept ●Use AtomOperation to Modify Critical Data ●Enter a Spin State When Atom Operation Fail Atom Operation Success? Finish No Yes
  • 8.
    Compare and Swap boolCAS(uint32* pointer, uint32 old_value, uint32 new_value) { if (*pointer == old_value) { *pointer = new_value; return true; } return false; } InterlockedCompareExchange - Windows API
  • 9.
    Other Atom Operation ●CAS2- Compare and Swap 2 ●CASN - Compare and Swap N ●DCAS - Double Compare Swap ●MCAS - Multiword Compare and Swap ●LL/SC - Load Linked / Store Conditional
  • 10.
    Example - Stack structNode { volatile Node* next; }; class Stack { volatile Node* head; public: void Push(Node* node); void Pop(); Stack() : head(0) {} }; void Stack::Push(Node* node) { while (true) { node->next = head; if (CAS(&head, node->next, node)) break; } } void Stack::Pop() { while (true) { node* old_head = head; if (head == 0) break; node* next_node = old_head->next; if (CAS(&head, old_head, next_node)) break; } } Something Wrong
  • 11.
    ABA Problem Thread A A B C A B C Head Pop ThreadB A B C Pop C A Push Head Head Head node* old_head = head; if (head == 0) break; node* next_node = old_head->next; if (CAS(&head, old_head, next_node)) break;
  • 12.
    Solute ABA Problem ●LL/SC ○Itwould return false when target have done a "write" action ●CAS2 ○Add a versioned value
  • 13.
    Example - Stack(fixPop) void Stack::Pop() { while (true) { node* old_head = head; int old_version = version; if (head == 0) break; node* next_node = old_head->next; if (CAS2(&head, old_head, old_version, next_node, old_version + 1)) break; } } class Stack { volatile Node* head; volatile int version; public: void Push(Node* node); void Pop(); Stack() : head(0), version(0) {} }; Add Version Check Version
  • 14.
    Summary ●Lock-Free has BetterPerformance Than Blocking ●Lock-Free has no "Lock" ●Lock-Free is Hard To Implement ●Lock-Free's Spirit - Atom Operation ●Lock-Free's Trap - ABA Problem
  • 15.
    Notes and References ●TobyJones - Lock-Free Algorithms(Game Programming Gems 6) ●Jean-Francois Dube - Efficient and Scalable Multi-Core Programming(Game Programming Gems 8) ●Zhou Wei Ming - Multi-core Computing and Programming
  • 16.
  • 17.
    Thanks for yourattention By PanPan 2010-06-29