티스토리 뷰

데드락 현상은

예를 들어 스레드 Process1 그리고 Process2 가 존재하고

서로 자원(Resource)을 점유하고있고 

P1 -> P2(점유하고있는 자원)

P2 -> P1(점유하고있는 자원)

접근할때 데드락 현상이 일어난다.

 

서로 점유하고있는 자원에 LOCK을 걸고있고 풀지않으니깐 일어나는 현상이다.

그러면 데드락현상을 한번 생성해보자.

 

 

#include <iostream>
#include <algorithm>
#include <thread>
#include <atomic>
#include <mutex>
#include "ItemRepository.h"
#include "UserRepository.h"
using namespace std;

ItemRepository itemRepository;
UserRepository userRepository;

void Func1() 
{
	for (int i = 0; i < 1000; i++) {
		userRepository.saveUser(&itemRepository);
	}
}


void Func2()
{
	for (int i = 0; i < 1000; i++) {
		itemRepository.saveItem(&userRepository);
	}
}

int main() 
{
	std::thread t1;
	std::thread t2;


	t1 = std::thread(Func1);
	t2 = std::thread(Func2);
	

	t1.join();

	t2.join();

	cout << "Job Done" << endl;

	return 0;
}

UserRepository 클래스의 saveUser를 실행하고

ItemRepository 클래스의  saveItem을 실행한다

 



void ItemRepository::saveItem(UserRepository* userRepository)
{
	// saveItem을 실행하는순간 Lock을 잠근다
	lock_guard<std::mutex> lock_guard(_mutex);
    // ItemRepository에서 Lock을 잠근후 FindByUserId를 실행한다.
	User* user = userRepository->FindByUserId(100);
}

// saveUser를 실행하는순간 Lock를 잠근다
void UserRepository::saveUser(ItemRepository* itemRepository)
{
	// saveItem을 실행하는순간 Lock을 잠근다
	lock_guard<std::mutex> lock_guard(_mutex);
    // UserRepository에서 Lock을 잠근후 FindByItemId를 실행한다.
	Item* item = itemRepository->FindByItemId(100);
}



User* FindByUserId(int userId) 
{
	
	lock_guard<std::mutex> lock_guard(_mutex);
	return nullptr;
}
    
    Item* FindByItemId(int itemId)
{
	lock_guard<std::mutex> lock_guard(_mutex);
	return nullptr;
}

지금 현재 위와 같은 상황이 발생했다.

ItemRepository와 

UserRepository는 멀티쓰레드에서 실행되기 때문에 누구 먼저 실행된다는 보장이 없다.

병렬적으로 실행되기에 동시에 내가 가진 자원에 Lock을 잠그고 서로 다른 자원에 접근한다면 교착상태에 빠지게 된다 

--- 상황

1) t1 스레드가 User Lock을 잠금

1) t2 스레드가 Item Lock을 잠금

 

2) t1 스레드가 Item 에 접근 하지만 t2가 Lock을 잠궜음

2) t2 스레드가 User 에 접근 하지만 t1이 Lock을 잠궜음

서로 이렇게 교착상태에 빠짐

 

 

 

 


void ItemRepository::saveItem(UserRepository* userRepository)
{
	
    // ItemRepository에서 FindByUserId를 실행한다 (하지만 saveUser에서 Lock을 잡았기때문에 대기).
	User* user = userRepository->FindByUserId(100);
    
    // saveItem을 실행하는순간 Lock을 잠근다
	lock_guard<std::mutex> lock_guard(_mutex);
}


void UserRepository::saveUser(ItemRepository* itemRepository)
{
	// saveUser를 실행하는순간 UserRepository Lock를 잠근다
	lock_guard<std::mutex> lock_guard(_mutex);
    // UserRepository에서 Lock을 잠근후 FindByItemId를 실행한다.
    // ItemLock잠김
 
	Item* item = itemRepository->FindByItemId(100);
    // Item Lock 해제
    // User Lock 해제 
}



User* FindByUserId(int userId) 
{
	
	lock_guard<std::mutex> lock_guard(_mutex);
	return nullptr;
}
    
    Item* FindByItemId(int itemId)
{
	lock_guard<std::mutex> lock_guard(_mutex);
	return nullptr;
}

이걸 해결해줄수 있는 방법은 간단한데, 서로의 순환구조를 풀어주는것이다.

-- 해결책

1) t1 스레드가 User에 접근하지만 Item이 Lock을 잠금 t2가 끝날때까지 대기함

2) t2 순차적으로 일을 처리한후 LOCK을 해제 

3) t1 스레드가 깨어남

4) t1 스레드가 일을 처리함

 

 

느낀점:
아직도 어렵다;

Comments
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday