일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 상태
- Prefix Sums
- stl
- series
- margin
- Gap
- c
- spring
- skt membership
- 수학
- 백준
- 포토샵
- pandas
- Codility
- 통신사할인
- Design Pattern
- c++
- CSS
- 확률
- 에라토스테네스의 체
- align-items
- 알고리즘
- Javascript
- dataframe
- Photoshop
- Flexbox
- grid
- 강화학습
- SK바이오사이언스
- 소수
Archives
- Today
- Total
sliver__
[Mastering C++ Programming] - deadlock 본문
728x90
- 다중 스레드 응용 프로그램에서는 deadlock 상태에 빠질 때까지 모든 것이 멋지고 흥미롭게 보입니다.
- READER와 WRITER라는 두 개의 스레드가 있다고 가정합니다.
- READER 스레드가 WRITER가 이미 획득한 잠금을 기다리고 WRITER 스레드가 READER가 소유한 잠금을 리더가 해제할 때까지 기다리거나 그 반대의 경우 교착 상태가 발생할 수 있습니다.
- 일반적으로 교착 상태 시나리오에서 두 스레드는 끝없이 서로를 기다립니다.
- 일반적으로 교착 상태는 설계 문제입니다.
- 때로는 교착 상태를 빠르게 감지할 수 있지만 때로는 근본 원인을 찾는 것이 매우 까다로울 수 있습니다.
- 따라서 결론은 동기화 메커니즘을 신중하게 올바른 의미로 사용해야 한다는 것입니다.
- 교착 상태 시나리오를 생성하기 위해 약간 수정하여 Thread 클래스를 재사용할 것입니다.
#include "Thread.h"
mutex Thread::commonLock;
int Thread::count = 0;
Thread::Thread( ThreadType typeOfThread ) {
pThread = NULL;
stopped = false;
threadType = typeOfThread;
(threadType == READER) ? name = "READER" : name = "WRITER";
}
Thread::~Thread() {
delete pThread;
pThread = NULL;
}
int Thread::getCount( ) {
cout << name << " is waiting for lock in getCount() method ..." <<
endl;
lock_guard<mutex> locker(commonLock);
return count;
}
int Thread::updateCount( ) {
cout << name << " is waiting for lock in updateCount() method ..." << endl;
lock_guard<mutex> locker(commonLock);
int value = getCount();
count = ++value;
return count;
}
void Thread::run( ) {
while ( 1 ) {
switch ( threadType ) {
case READER:
cout << name<< " => value of count from getCount() method is " << getCount() << endl;
this_thread::sleep_for ( 500ms );
break;
case WRITER:
cout << name << " => value of count from updateCount() method is" << updateCount() << endl;
this_thread::sleep_for ( 500ms );
break;
}
}
}
void Thread::start( ) {
pThread = new thread ( &Thread::run, this );
}
void Thread::stop( ) {
stopped = true;
}
void Thread::join( ) {
pThread->join();
}
void Thread::detach( ) {
pThread->detach( );
}
- Thread::getCount() 및 Thread::updateCount() 메서드에 대한 논의에 집중하겠습니다.
- std::lock_guard<std::mutex>는 mutex::unlock()을 호출하지 않도록 하는 템플릿 클래스입니다.
- 스택 해제 프로세스 중에 lock_guard 소멸자가 호출됩니다.
- 이렇게 하면 mutex::unlock()이 호출됩니다.
- 결론은 std::lock_guard<std::mutex> 인스턴스가 생성된 시점부터 메소드 끝까지 나타나는 모든 문은 뮤텍스에 의해 보호된다는 것입니다.
#include <iostream>
using namespace std;
#include "Thread.h"
int main ( ) {
Thread reader( READER );
Thread writer( WRITER );
reader.start( );
writer.start( );
reader.join( );
writer.join( );
return 0;
}
- 두 개의 스레드, 즉 reader와 writer를 생성했으며 각 스레드가 생성된 후 시작됩니다.
- 기본 스레드는 reader / writer 스레드가 종료될 때까지 기다려야 합니다.
- WRITER 스레드는 Thread::updateCount() 메서드를 호출하고, 이는 차례로 Thread::getCount() 메소드를 호출합니다.
- Thread::updateCount() 메서드가 먼저 잠금을 획득한 다음 Thread::getCount() 메서드를 호출했음이 인쇄 문에서 분명합니다.
- 그러나 Thread::updateCount() 메서드가 뮤텍스 잠금을 해제하지 않았으므로 WRITER 스레드에서 호출한 Thread::getCount() 메서드를 진행할 방법이 없습니다.
- 한편 OS 스케줄러는 READER 스레드를 시작했으며 WRITER 스레드가 획득한 뮤텍스 잠금을 기다리는 것 같습니다.
- 따라서 READER 스레드가 작업을 완료하려면 Thread::getCount() 메서드에 대한 잠금을 획득해야 합니다.
- 그러나 이는 WRITER 스레드가 잠금을 해제할 때까지 불가능합니다.
- WRITER 스레드는 자신의 Thread::getCount() 메서드 호출이 작업을 완료할 때까지 작업을 완료할 수 없습니다.
- 이를 교착 상태라고 합니다.
- 설계 또는 논리적 문제입니다.
- Unix 또는 Linux에서는 Helgrind 도구를 사용하여 유사한 동기화 문제를 처리하여 교착 상태를 찾을 수 있습니다.
- Helgrind 도구는 Valgrind 도구와 함께 제공됩니다.
- deadlock 또는 condition race로 이어지는 소스 줄 번호를 얻으려면 이제 -g 플래그로 표시된 것처럼 디버그 모드에서 코드를 컴파일해야 합니다.
valgrind --tool=helgrind ./a.out
728x90
'CS > C++' 카테고리의 다른 글
[Mastering C++ Programming] - Condition variable (0) | 2022.12.09 |
---|---|
[Mastering C++ Programming] - Shared Mutex (0) | 2022.12.09 |
[Mastering C++ Programming] - Mutex (0) | 2022.12.08 |
[Mastering C++ Programming] - Thread Synchronization (0) | 2022.12.08 |
[Mastering C++ Programming] - How to write a multithreaded application using the native C++ thread feature (0) | 2022.12.08 |
Comments