프로그래밍
-
데드락(Deadlock)과 라이브락(Livelock)프로그래밍/기록, 개념, 용어 2015. 2. 5. 02:17
데드락과 라이브락 데드락(Deadlock) 데드락은 스레드들이 서로 상대방이 가진 자원을 기다리느라 전혀 진도를 나가지 못하는 상황이다. 두 개의 뮤텍스 락 A, B를 모두 획득하려는 두 개의 스레드를 예를 들어보자.스레드0이 락A를 스레드1이 락B를 각각 획득한 상태라면 스레드0은 B를 확보할 수가 없어 작업 진행을 할 수 없고,스레드1은 락A를 확보할 수 없어 작업을 진행하지 못한다. Thread0 void update(){ 획득(A) 획득(B) // 스레드0은 여기서 무한 대기 어떤작업() 해제(B) 해제(A)} Thread1 void update(){ 획득(B) 획득(A) // 스레드1은 여기서 무한 대기 어떤작업() 해제(A) 해제(B)} 라이브락(Livelock) 라이브락은 두 스레드가 락의 ..
-
데이터 레이스(Data Race)프로그래밍/기록, 개념, 용어 2015. 2. 5. 01:55
데이터 레이스는 다중 스레드 프로그래밍을 할 때 범하기 쉬운 오류 중 하나이다. 데이터 레이스는 멀티 스레드를 이용하는 환경에서, 같은 데이터를 이용하고 다른 스레드에서 그것을 업데이트 할 때 발생한다. 아래와 같은 코드가 있다. // a를 읽어 %o1에 저장 // %o1에 4를 더함 // %o1를 a에 저장 void update_int( int* data ) { *a = *a + 4; } 이 코드가 멀티 스레드로 구동되고, 두 스레드에서 동시에 같은 데이터의 값을 증가시키려 할 때는 이런 상황이 발생할 수 있다. int a = 10; // a는 여러 쓰레드에서 공유가 되고있는 변수이다. Thread[0] a를 읽어 %o1에 저장 %o1에 4를 더함 %o1의 값을 a에 저장 Thread[1] a를 읽어 ..
-
뮤텍스(Mutex)와 크리티컬 리전/섹션(Critical Region/Section)프로그래밍/기록, 개념, 용어 2015. 2. 5. 01:53
뮤텍스(Mutex)와 크리티컬 리전/섹션(Critical Region/Section) 가장 단순한 동기화 장치는 상호 배타적인 잠금 매커니즘인 뮤텍스이다.뮤텍스를 사용하면 락을 획득한 스레드만이 그 구역에 접근이 가능하므로, 특정 데이터 구조를 뮤텍스 락으로 둘러싸면 한 시점에 한 스레드만 접근하게 만들 수 있다. int counter = 0; void inc(){ acquire(mutex); ++counter; release(mutex); } void dec() { acquire(mutex); --counter; release(mutex); }여러 개의 스레드가 같은 뮤텍스 락을 동시에 얻으려고 시도해도 한 스레드만 락을 얻고, 다른 스레드들은 대기하게 된다. 락을 얻기 위해 대기하는 상황을 Conte..
-
원자적 조작과 락-프리 코드(Atomic operation & Lock-Free code)프로그래밍/기록, 개념, 용어 2015. 2. 5. 01:51
원자적 조작과 락-프리 코드(Atomic operation & Lock-Free code) 동기화 장치를 사용하면 높은 오버헤드가 따른다.어떤 경우에는 원자적 조작을 이용하거나, 락 프리 형태로 동등한 작업을 구현하는 것이 오버헤드를 피하는 한 방법이 될 수 있다.원자적 조작이 수행되는 중간에는 다른 스레드가 끼어들 여지가 없고, 중간 결과를 시스템에서 엿보는 것도 불가능하다.왜냐? 원자적(Atomic)이므로 쪼개질 수 없기 때문이다. 일반적인 변수인 A를 A+1로 바꾸는 작업은 아주 단순해보이지만 다음과 같은 단계를 거친다.A를 로딩해 %o1에 저장%o1의 값을 증가시킴%o1를 A에 저장이 3단계의 명령 수행을 진행하는데에는 각 단계마다 다른 스레드에서 간섭할 수도 있고, 변수가 위치한 메모리에 값을 ..
-
배리어(Barrier)프로그래밍/기록, 개념, 용어 2015. 2. 5. 01:47
배리어(Barrier) 특정 작업을 시작하기 전에, 다른 스레드가 모두 완료되어야만 하는 때가 있을 수 있다. 이럴때 배리어를 이용하면 다른 스레드가 작업을 완료할 때까지 대기할 수 있다. 전형적인 사용 시기는 서로 다른 두 코드가 종속성을 가질 때다. 아래 코드에서 변수 total은 행렬의 각 항목에 값이 모두 설정되어야만 계산될 수 있다. 배리어를 이용하면 변수 total을 계산하기 전에 행렬에 값을 설정하는 모든 스레드가 완료하는 것을 보장한다. 배리어를 이용한 순서 보증 compute_values_held_in_mat();barrier(); // 배리어total = calc_value_from_mat();
-
포인터 에일리어스(Pointer Alias)프로그래밍/기록, 개념, 용어 2015. 2. 4. 21:20
포인터 에일리어스(Pointer Alias) 두 개 이상의 포인터 변수가 같은 메모리 위치를 담고 있을 때 그 포인터들을 에일리어스(alias)라고 부른다.컴파일러 입장에선 모든 포인터 변수가 서로의 에일리어스 일 수도 있다 생각하는 것이 안전하다. 포인터 에일리어스 발생 가능성이 높은 코드 void any_func( int* a, int* b ){ *b = *b + *a; *a = *a + 2; } 포인터 a, b가 에일리어스 상태가 아니라면 a의 값은 한 번만 로딩되면 된다. 에일리어스일 경우에는 포인터 b가 지칭하는 값에 대한 수정이 a가 지칭하는 값에 대한 수정일 수 있으므로 a의 값이 두 번 로딩되어야 한다. 포인터 에일리어싱이 가능한 코드 void func( int* a, int* b ) { ..