Visible to Intel only — GUID: GUID-4D3BF5DA-C971-4065-87A1-D5A2E5F640CA
Visible to Intel only — GUID: GUID-4D3BF5DA-C971-4065-87A1-D5A2E5F640CA
Lock Hierarchy Violation
Occurs when two or more locks are acquired in a different order in two task executions, potentially leading to a deadlock when the program's tasks execute in parallel.
A Lock hierarchy violation problem indicates the following timeline:
Task 1 |
|
Task 2 |
|
If these time lines are interleaved when the two tasks execute in parallel, a Deadlock occurs:
Task 1: Acquire lock A.
Task 2: Acquire lock B.
Task 1: Try to acquire lock B; wait until task 2 releases it.
Task 2: Try to acquire lock A; wait until task 1 releases it.
The Dependencies tool reports a Lock hierarchy violation as multiple problems in a problem set. Each problem shows a portion of the Lock hierarchy violation from the perspective of a single thread.
Lock hierarchy violation problems are the most common cause of Deadlock problems, and a report of a Lock hierarchy violation problem indicates a Deadlock problem might occur when the target executes in parallel.
Syntax
ID |
Code Location |
Description |
---|---|---|
1 |
Allocation site |
If present, represents the location and its associated call stack where the synchronization object acquired by a thread (usually the object acquired first) was created. |
2 |
Parallel site |
If present, represents the location and associated call stack of the parallel site containing the Lock Hierarchy Violation problem. |
3 |
Lock owned |
Represents the location and associated call stack where a task acquired a lock. |
4 |
Lock owned |
Represents the location and associated call stack where a task acquired a second lock while the task still held the first lock. |
Example
// in task 1 |
ANNOTATE_LOCK_ACQUIRE(&lahv_lock1); ANNOTATE_LOCK_ACQUIRE(&lahv_lock2); /* lock hierarchy violation */ ANNOTATE_LOCK_RELEASE(&lahv_lock2); ANNOTATE_LOCK_RELEASE(&lahv_lock1); |
// in task 2 |
ANNOTATE_LOCK_ACQUIRE(&lahv_lock2); ANNOTATE_LOCK_ACQUIRE(&lahv_lock1); /* lock hierarchy violation */ ANNOTATE_LOCK_RELEASE(&lahv_lock1); ANNOTATE_LOCK_RELEASE(&lahv_lock2); |
Possible Correction Strategies
Determine if interleaving is possible, or whether some other synchronization exists that might prevent interleaving. If interleaving is possible, consider the following options.
Use a single lock instead of multiple locks:
// in task 1 |
ANNOTATE_LOCK_ACQUIRE(&lahv_lock1); a++; b += a; ANNOTATE_LOCK_RELEASE(&lahv_lock1); |
// in task 2 |
ANNOTATE_LOCK_ACQUIRE(&lahv_lock2); b += x[i]; a -= b; ANNOTATE_LOCK_RELEASE(&lahv_lock2); |
Try to define a consistent order for your locks, so that any task that acquires the same set of locks, will acquire them in the same order:
// in task 1 |
ANNOTATE_LOCK_ACQUIRE(&lahv_lock1); a++; b += a; ANNOTATE_LOCK_RELEASE(&lahv_lock1); |
// in task 2 |
ANNOTATE_LOCK_ACQUIRE(&lahv_lock2); b += x[i]; a -= b; ANNOTATE_LOCK_RELEASE(&lahv_lock2); |
When a task acquires multiple locks, make sure that it always releases them in the opposite order that it acquired them.