리눅스

Dead lock과 pthread에서 mutex lock하는 방법

개발새발 2018. 1. 7. 15:55
반응형


공유자원(파일)에 대해서 pthread의 lock에 대해 알아보던 중 pthread_mutex_lock 외에도 pthread_mutex_trylock, pthread_mutex_timedlock이 있다는걸 알게되었다.

추가적으로 dead lock 가능성을 피하기 위해 잠시 dead lock에 대해 복습해 보면 dead lock 두가지 상황에서 발생할 수 있다. 
1) A thread에서 mutex lock변수 a를 이용해서 lock을 진행한 상태에서 다시 a를 lock 하려고 할때 발생.(보통 재귀적으로 구현 된 함수에서 lock을 거는 경우 발생함)

2) A thread에서 mutex lock변수 a를 lock하고 B thread에서 mutex lock변수 b를 lock을 한 상태에서 A thread에서 b를 이용해서 lock을 시도하는 경우 발생.

dead lock이 안생기도록 로직을 짜는게 최선이지만 현실적으로 어느 상황에서 dead lock이 발생할지 예상하기 힘들다.

pthread mutex lock함수를 보면 다음과 같다
  • int pthread_mutex_lock(pthread_mutex_t *mutex);
  • int pthread_mutex_trylock(pthread_mutex_t *mutex);
  • int pthread_mutex_timedlock(pthread_mutex_t *restrict mutexconst struct timespec *restrict abs_timeout); 
각각의 함수마다 조금씩 기능이 다른데 구현 하려는 프로그램에 맞게 적절히 사용하면 된다.

간단한게 특성을 보면 pthread_mutex_lock의 경우 해당 lock이 사용중인 경우 unlock될 때 까지 lock을 구하는 쓰레드는 블락된다.(dead lock의 주된 원인)
pthread_mutex_trylock은 사용하려는 lock이 사용중이면 EBUSY를 리턴하고 사용가능 할 경우 임계영역에 접근한다.
phtread_mytex_timedlock timespec 구조체에 sec와 nano sec를 설정하면 설정 된 시간안에 lock을 획득하지 못하면 오류를 반환함.


예제 코드



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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
 
pthread_mutex_t mutex_lock;
 
void* test_mutex_lock(void *data){
 
    pthread_mutex_lock(&mutex_lock);
 
    for(int i=0;i<5;i++){
 
        printf("test_mutex_lock :%d\n",i);
 
        sleep(1);
 
    }
 
    pthread_mutex_unlock(&mutex_lock);
 
    return NULL;
 
}
 
 
 
void* test_mutex_try_lock(void *data){
 
    if(pthread_mutex_trylock(&mutex_lock)==0){//NOT EBUSY
 
        for(int i=0;i<5;i++){
 
            printf("test_mutex_try_lock :%d\n",i);
 
            sleep(1);
 
        }
 
        pthread_mutex_unlock(&mutex_lock);
 
    }else{
 
        printf("test_mutex_try_lock failed!\n");
 
    }
 
    return NULL;
 
}
 
 
 
void* test_mutex_timed_lock(void *data){
 
    struct timespec ts;
 
    ts.tv_sec=1;
 
    ts.tv_nsec=0;
 
    pthread_mutex_timedlock(&mutex_lock,&ts);
 
    for(int i=0;i<5;i++){
 
        printf("test_mutex_timed_lock :%d\n",i);
 
        sleep(1);
 
    }
 
    pthread_mutex_unlock(&mutex_lock);
 
    return NULL;
 
}
 
 
 
int main(void){
 
    pthread_t pid[3];
 
    int thr_id;
 
    int status;
 
    pthread_mutex_init(&mutex_lock, NULL);
 
    
 
    thr_id = pthread_create(&pid[0], NULL, test_mutex_lock, NULL);
 
    if (thr_id < 0)
 
    {
 
        perror("thread create error : ");
 
        exit(0);
 
    }
 
    
 
    thr_id = pthread_create(&pid[1], NULL, test_mutex_try_lock, NULL);
 
    if (thr_id < 0)
 
    {
 
        perror("thread create error : ");
 
        exit(0);
 
    }
 
    
 
    thr_id = pthread_create(&pid[2], NULL, test_mutex_timed_lock, NULL);
 
    if (thr_id < 0)
 
    {
 
        perror("thread create error : ");
 
        exit(0);
 
    }
 
    
 
    pthread_join(pid[0], (void **)&status);
 
    pthread_join(pid[1], (void **)&status);
 
    pthread_join(pid[2], (void **)&status);
 
    
 
    return 0;
 
cs
반응형