[C++]DeadLock

강병우·2023년 8월 1일
0

DeadLock

여러 프로세스가 하나의 자원을 점유하려고 하는 상황이 발생할 수도 있다. 이 때, 프로세스가 점유하고 있는 자원에 또 다른 프로세스가 점유하기 위해 기다리게 된다. 이 현상이 무한루프에 빠지는 것을 DeadLock이라고 한다.


DeadLock 조건

DeadLock 상태가 발생하는 조건은 4가지로 정리된다.

  • 상호배제
    한 번에 하나의 프로세스만 해당 자원을 사용할 수 있다. 만약 사용중인 자원을 다른 프로세스가 사용하려면 요청한 자원이 해제될 때까지 대기해야 한다.
  • 점유 대기
    자원을 보유하고 있고, 다른 프로세스에 할당된 자원을 점유하기 위해 대기하는 프로세스가 존재해야 한다.
  • 비선점
    이미 점유 중인 자원을 강제로 뺏을 수 없다.
  • 순환 대기
    대기 프로세스의 집합이 순환 형태로 자원을 대기해야 한다.

DeadLock 회피

  • 예방
    교착상태 발생 조건 중 하나를 제거한다. 하지만, 리소스 소모가 심하다.
  • 회피
    교착상태에 빠지지 않도록 알고리즘을 적용한다. 은행원 알고리즘이 대표적이다.
  • 탐지
    탐지 알고리즘을 통해 교착상태를 찾아내곻 복구 기법을 통해 교착상태를 복구한다. 매번 탐지를 해야 하기 때문에 리소스 소모가 있다.
  • 무시
    아예 무시한다. 교착상태를 해결하기 위해 발생하는 리소스 낭비가 방치했을 때보다 큰 경우에 무시한다.

예제

C++에서는 mutex를 기반으로 하여 Deadlock 상태를 방지한다. lock_guard는 객체 생성 시 lock이 되며, 객체가 소멸하면 자동으로 unlock된다.

  • main 코드
#include "pch.h"
#include <iostream>
#include "CorePch.h"
#include <thread>
#include <atomic>
#include <mutex>
#include "AccountManager.h"
#include "UserManager.h"

void Func1()
{
	for (int32 i = 0; i < 1000; i++)
	{
		UserManager::Instance()->ProcessSave();
	}
}

void Func2()
{
	for (int32 i = 0; i < 1000; i++)
	{
		AccountManager::Instance()->ProcessLogin();
	}
}


int main()
{
	thread t1(Func1);
	thread t2(Func2);

	t1.join();
	t2.join();

	cout << "Jobs Done" << endl;
}
  • UserManager
void UserManager::ProcessSave()
{

	// accountLock
	Account* account = AccountManager::Instance()->GetAccount(100);

	// userLock
	lock_guard<mutex> guard(_mutex);

	// accountLock
	// Account* account = AccountManager::Instance()->GetAccount(100);
	// 이 상태일경우, user와 account 모두 lock이 걸릴 수도 있다.
	// 따라서, accountLock의 순서를 첫번째로 수정하면 deadlock에 걸리지 않는다.
}
  • AccountManager
#include "pch.h"
#include "AccountManager.h"
#include "UserManager.h"

void AccountManager::ProcessLogin()
{
	// accountLock
	lock_guard<mutex> guard(_mutex);

	// userLock
	User* user = UserManager::Instance()->GetUser(100);
}

0개의 댓글

관련 채용 정보