라인 동기화: 귀속 자물쇠, 비귀속 자물쇠
1.1 프로세스/스레드 동기화 방법
흔히 볼 수 있는 프로세스/루틴 동기화 방법에는 상호 배척 자물쇠(또는 상호 배척 Mutex), 읽기 자물쇠(rdlock), 조건 변수(cond), 신호량(Semophore) 등이 있다.
윈도우즈 시스템에서도 임계 영역(Critical Section)과 이벤트 객체(Event)가 자주 사용되는 동기화 방법입니다.
1.2 귀속 잠금/비귀속 잠금
Mutex는 반복 잠금(recursive mutex)과 비반복 잠금(non-recursive mutex)으로 나눌 수 있다.귀속 자물쇠도 다시 들어갈 수 있는 자물쇠(reentrant mutex)라고 하고, 비귀속 자물쇠도 다시 들어갈 수 없는 자물쇠(non-reentrant mutex)라고 한다.
양자의 유일한 차이점은 다음과 같다.
같은 라인에서 같은 귀속 자물쇠를 여러 번 얻을 수 있으며, 고정 자물쇠가 생기지 않는다.
만약 한 라인이 같은 비귀속 자물쇠를 여러 번 얻게 된다면, 사라진 자물쇠가 생길 것이다.
Windows의 Mutex 및 Critical Section은 재귀속적입니다.
Linux의 pthreadmutex_t 자물쇠는 기본적으로 비귀속적입니다.PTHREADMUTEX_RECURSIVE 속성, pthreadmutex_t 자물쇠를 귀속 자물쇠로 설정합니다.
코드
2.1 Critical Section 폴드 잠금
#include <Windows.h>
#include <iostream>
#include <string>
int counter = 0;
CRITICAL_SECTION g_cs;
void doit(void* arg)
{
int i, val;
for (i=0; i<5000; i++)
{
EnterCriticalSection(&g_cs);
EnterCriticalSection(&g_cs);
val = counter;
printf("thread %d : %d
", int(arg), val+1);
counter = val + 1;
LeaveCriticalSection(&g_cs);
LeaveCriticalSection(&g_cs);
}
}
int main(int argc, char*argv[])
{
InitializeCriticalSection(&g_cs);
HANDLE hThread1 = CreateThread(NULL,0, (LPTHREAD_START_ROUTINE)doit, (void*)1, 0, NULL);
HANDLE hTrehad2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)doit, (void*)2, 0, NULL);
WaitForSingleObject(hThread1, INFINITE);
WaitForSingleObject(hTrehad2, INFINITE);
DeleteCriticalSection(&g_cs);
return 0;
}
결과: 자물쇠 1회와 자물쇠 2회를 추가하면 1~10000을 정확하게 출력할 수 있다.
2.2 pthread_mutex_t 비귀속 잠금
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int counter = 0;
pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
void* doit(void*)
{
int i, val;
for (i=0; i<5000; i++)
{
pthread_mutex_lock(&g_mutex);
pthread_mutex_lock(&g_mutex);
val = counter;
printf("%x: %d
", pthread_self(), val+1);
counter = val + 1;
pthread_mutex_unlock(&g_mutex);
pthread_mutex_unlock(&g_mutex);
}
}
int main(int argc, char*argv[])
{
pthread_t tid1, tid2;
pthread_create(&tid1, NULL, doit, NULL);
pthread_create(&tid2, NULL, doit, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
return 0;
}
결과: 자물쇠를 1회 추가하면 1~10000을 정확하게 출력할 수 있습니다.자물쇠를 2회 추가하고, 자물쇠를 닫으며, 아무런 정보도 출력하지 않습니다.
2.3 pthread_mutex_t 반복 잠금(PTHREAD MUTEX RECURSIVE)
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int counter = 0;
pthread_mutex_t g_mutex;// = PTHREAD_MUTEX_INITIALIZER;
void* doit(void*)
{
int i, val;
for (i=0; i<5000; i++)
{
pthread_mutex_lock(&g_mutex);
pthread_mutex_lock(&g_mutex);
val = counter;
printf("%x: %d
", pthread_self(), val+1);
counter = val + 1;
pthread_mutex_unlock(&g_mutex);
pthread_mutex_unlock(&g_mutex);
}
}
int main(int argc, char*argv[])
{
//create recursive attribute
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
//set recursive attribute
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&g_mutex, &attr);
pthread_t tid1, tid2;
pthread_create(&tid1, NULL, doit, NULL);
pthread_create(&tid2, NULL, doit, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
pthread_mutex_destroy(&g_mutex);
//destroy recursive attribute
pthread_mutexattr_destroy(&attr);
return 0;
}
결과: 1회 자물쇠와 2회 자물쇠를 추가하면 모두 1~10000을 정확하게 출력할 수 있다.참조 자료:http://blog.chinaunix.net/uid-26983585-id-3316794.html
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.