Tip: Lock Leveling | CodeGuru

Tip: Lock Leveling

This article introduces the use of lock leveling to prevent deadlocks. Lock leveling is also known as lock ordering, lock ranking and lock hierarchies. Lock leveling always acquire the locks in relative order to prevent deadlocks. Let us look at a simple deadlock example. void Thread1() { lock lock1(A); { lock lock2(B); {…} } } […]

Written By
CodeGuru Staff
CodeGuru Staff
Mar 19, 2009
2 minute read
CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More

This article introduces the use of lock leveling to prevent deadlocks.
Lock leveling is also known as lock ordering, lock ranking and lock hierarchies. Lock leveling always acquire the locks in relative order to prevent deadlocks. Let us look at a simple deadlock example.

void Thread1()
{
	lock lock1(A);
	{
		lock lock2(B);
		{...}
	}
}

void Thread2()
{
	lock lock1(B);
	{
		lock lock2(A);
		{...}
	}
}

If Thread1 holds lock A while waiting to hold lock B and at the same time
Thread2 holds lock B while waiting to hold lock A, both threads fail to get the
locks they want, thus a deadlock occurs.

void Thread1()
{
	lock lock1(A,B);
	{
		...
	}
}

void Thread2()
{
	lock lock1(B,A);
	{
		...
	}
}

If we could acquire all the locks at the same time in a atomic operation as shown
above, we could solve the problem. However that is not possible. One obvious way to
solve this is to always take locks in relative order. One way is to encapsulate the mutex
or critical section in a class and add a unique relative number as member to this class.
Then lock these mutex or critical section class using a RAII lock class which will always sort the instances of mutex or critical section class before acquiring the lock, so they will always be acquired in the same order. This RAII lock class will release the locks in its destructor. The order of releasing the locks does not matter as releasing the locks does not
result in a deadlock. Below is an example of the RAII lock leveling class.

// A RAII lock leveling class
class Lock
{
public:
	explicit Lock(CritSectLock& a);
	explicit Lock(CritSectLock& a, CritSectLock& b);
	explicit Lock(CritSectLock& a, CritSectLock& b, CritSectLock& c);
	explicit Lock(CritSectLock& a, CritSectLock& b, CritSectLock& c, CritSectLock& d);
	explicit Lock(CritSectLock& a, CritSectLock& b, CritSectLock& c, CritSectLock& d, CritSectLock& e);
	~Lock(void);
private:
	void LockAll();
	std::vector<CritSectLock*> m_vec;
};

Lock::Lock(CritSectLock& a)
{
	m_vec.push_back(&a);
	LockAll();
}

Lock::Lock(CritSectLock& a, CritSectLock& b)
{
	m_vec.push_back(&a);
	m_vec.push_back(&b);
	LockAll();
}

Lock::Lock(CritSectLock& a, CritSectLock& b, CritSectLock& c)
{
	m_vec.push_back(&a);
	m_vec.push_back(&b);
	m_vec.push_back(&c);
	LockAll();
}

Lock::Lock(CritSectLock& a, CritSectLock& b, CritSectLock& c, CritSectLock& d)
{
	m_vec.push_back(&a);
	m_vec.push_back(&b);
	m_vec.push_back(&c);
	m_vec.push_back(&d);
	LockAll();
}

Lock::Lock(CritSectLock& a, CritSectLock& b, CritSectLock& c, CritSectLock& d, CritSectLock& e)
{
	m_vec.push_back(&a);
	m_vec.push_back(&b);
	m_vec.push_back(&c);
	m_vec.push_back(&d);
	m_vec.push_back(&e);
	LockAll();
}

struct CritSectLockComp : public std::binary_function<CritSectLock*, CritSectLock*, bool>
{
	bool operator()(CritSectLock* a, CritSectLock*b )
	{
		return ( a->GetIndex() < b->GetIndex() );
	}
};

void Lock::LockAll()
{
	std::sort(m_vec.begin(),m_vec.end(), CritSectLockComp());
	for(size_t i=0; i<m_vec.size(); ++i)
	{
		m_vec[i]->Enter();
	}
}

Lock::~Lock(void)
{
	for(size_t i=0; i<m_vec.size(); ++i)
	{
		m_vec[i]->Leave();
	}
}

Below is an example on how to use the Lock class.

// CritSectLock instances are declared elsewhere
CritSectLock a;
CritSectLock b;
CritSectLock c;

void foo()
{
	Lock lock(c,b,a); // The order of the arguments doesn't matter
	// as a, b and c will acquired in a ascending order.

	// Your code is here.
	//....

	// a, b and c will be released by the destructor of Lock calss
}

References

CodeGuru Logo

CodeGuru covers topics related to Microsoft-related software development, mobile development, database management, and web application programming. In addition to tutorials and how-tos that teach programmers how to code in Microsoft-related languages and frameworks like C# and .Net, we also publish articles on software development tools, the latest in developer news, and advice for project managers. Cloud services such as Microsoft Azure and database options including SQL Server and MSSQL are also frequently covered.

Property of TechnologyAdvice. © 2026 TechnologyAdvice. All Rights Reserved

Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.