블로그는 나의 힘!
[ Programing ]/Server2010. 6. 16. 17:02
1. 4가지 조건이 만족해야 데드락 발생
: Deadlock의 발생은 네트워크의 스레드나 데이터베이스에서나 발생 상황은 같다. 
 
1) mutual exclusion
- 자원이 공유(동시진입)되지 않음
- 동시에 단 한개의 쓰레드(프로세스)만이 자원에 접근 가능함

2) hold and wait
- 한 쓰레드(프로세스)에서 동시에 두개의 자원을 가져야만, 처리가능한 연산
- 두개의 자원을 동시에 필요로 하는 연산처리

3) no preemption
- 일단 한개의 자원을 어떤 쓰레드(프로세스)가 강점하면, 그 누구도 뺏을 방법이 없음

4) circular wait
- 자원에 대해 대기 그래프를 그려보면, 이 그래프에는 cycle이 존재
- 서로 서로 자원을 링크 소유
 
-------------------------------------------- 
 
2. 데드락 발생 시키게 하지 않을려면

1) mutual exclusion
- 자원을 공유하게 만든다 (완전! 재진입되게 만든다)
- 실전에서는 아주 어려운 작업 (운영체제 만드는 수준의...)

2) hold and wait
- 동시에 한개 이상의 자원을 요구하지 못하게 한다.
- 데드락이 될지 모르는 모든 요청에 대해 reject한다.
- 모든 자원에 대한 모든 접근은 동시에 이뤄지게 한다.
- 현재 소유한 자원을 free한 이후에 동시에 다수개 자원을 요청하도록 한다.

3) no preemption
- 자원을 preemtable하게 한다
- 실전에서는 아주 어려운 작업임
- 역시 운영체제 제작하는 수준의 코드가 필요...

4) circular wait
- 자원에 대해 순차적으로 요청하게 만든다.
 
----------------------------------------------
 
3. 락을 걸고 조용히 사망한 경우
즉, lock건 쓰레드가 unlock하게 내정된 구조인데, 영원히 unlock하지 않는"에 해당하므로
다음과 같이 해석.

 
1) mutual exclusion
- lock은 해제하기 전에 풀리지 않는다.
이때 아무도 재진입이 불가하다.

2) hold and wait
- lock을 걸고 무한히 기다리고 있는 형국이다.

3) no preemption
- 그 어떤 코드도 락을 풀려고 하지 않고 있다.
4) circular wait
- 락이 풀리기를 모두 대기하고 있다.

---------------------------------------------------
 
※ (발생 상황 EX) Multi thread
1) Lock 을 하고 Unlock 하지 않았을 때 무한 대기.
 void* ThreadLinkFunction( void* arg )
{
    for( int i = 0; i  < THREAD_CYCLE; i++ )
   {
        pthread_mutex_lock( (pthread_mutex_t*)arg );
        sleep(1);
        //pthread_mutex_unlock( (pthread_mutex_t*)arg );
   }
     ...
}
 
2) 양쪽 스레드에서 Lock을 잘못 사용할 때.
 
 void* Thread_ALinkFunction( void* arg )
{
    for( int i = 0; i  < THREAD_CYCLE; i++ )
   {
        pthread_mutex_lock( &mutex1 );
        sleep(1);
        pthread_mutex_lock( &mutex2 );
        sleep(1);
        pthread_mutex_unlock( &mutex2 );
       
        pthread_mutex_unlock( &mutex1 );
   }
     ...
}
 
 void* Thread_BLinkFunction( void* arg )
{
    for( int i = 0; i  < THREAD_CYCLE; i++ )
   {
        pthread_mutex_lock( &mutex2 );
        sleep(1);
        pthread_mutex_lock( &mutex1 );
        sleep(1);
        pthread_mutex_unlock( &mutex1 );
       
        pthread_mutex_unlock( &mutex2 );
   }
     ...
}
 
3) 무한 대기 상태나 오랫동안 리소스를 차지 할때
 
 void* ThreadLinkFunction( void* arg )
{
    for( int i = 0; i  < THREAD_CYCLE; i++ )
   {
        pthread_mutex_lock( &mutex1 );
 
        while(true) {}
        sleep(1);
        pthread_mutex_unlock( &mutex1 );
   }
     ...
}
 
※ (발생 상황 EX) Database
테이블 변경 및 삽입 후 commit으로 트랜잭션을 완료 하지 않을 때. 
unique와 무결성을 유지 하기 위해 변경한 데이터 유지를 위해 락이 걸려 있는 상태에서 상대방 테이블에 서로 서로 접근 시 무한 대기 상태.
 
user_1
SQL> Alter table employees add column email varchar(40);
SQL> Alter table user_2.employees add column email varchar(40);
 
user_2 
SQL> Alter table employees add column job_address varchar(60);
SQL> Alter table user_1.employees add column job_address varchar(60);
 
 
---------------------------------------------------
 
4. Critical Section 내에서 피해야 좋은 코드들

- thread 또는, process가 사망할 가능성이 있는 코드는 피한다.
- 위험한 길은 조심하다가 빠르게 지나가듯이, 빠르게 수행하도록 코드를 잘 보정한다.
- 무한히 다른 것(조건, 입력 등등)을 기다리는 코드는 피한다.
- Lock을 걸때는 아주 간단한 코드에 대해서 걸도록 유의한다.(함수 등을 필할 수 있으면 아주 좋다)
- Lock내에서 사용된 코드는 아주 간결하게 작성한다.
- 혹시, thread 또는 process가 정상 또는 비정상 사망할 경우 소유한 자산(자원)은 반드시 반납하게 작성한다.
(C++의 smart pointer등 scope에 의한 guard 메카니즘처럼 프로그램 언어수준에서 자원반납에 대한 확실한 메카니즘을 제공하는 좋은 것들을 사용하는것이 좋다.)
 
- 데이터베이스는 변경 및 수정 완료 후 commit이나 rollback 한다.
 


'[ Programing ] > Server' 카테고리의 다른 글

이벤트 객체 CreateEvent, SetEvent, ResetEvent, PulseEvent  (0) 2012.12.04
Shared memory  (0) 2010.07.23
메모리 락  (0) 2010.06.29
POSIX 정규 표현식  (0) 2010.06.29
Mutex 설정  (0) 2010.06.16
Posted by Mister_Q