- [C++] window, linux lock2022년 07월 15일
- starryeye
- 작성자
- 2022.07.15.:33
lock 이란.. 공유되는 자원에 동시 접근하여 데이터의 신뢰도를 떨어트리는 현상을 방지하고자 함에 있다.
따라서 lock이라는 개념을 도입하여 한번에 하나의 작업을 진행하게 한다.
그렇다면.. 여러 스레드에서 어떻게.. 그 자원에 lock이 걸려있는지 알 수 있을까?
-> 아래 os별 lock을 구현 하는 코드로 알아보자
window
window.h 헤더파일을 사용한다.
/////////////// 헤더 파일 class lockTest { 함수 선언 생략.. CRITICAL_SECTION* p_lock; } /////////////// cpp 파일 lockTest::lockTest() { p_lock = NULL; initialize(); } lockTest::~lockTest() { destroy(); } int lockTest::initialize() { CRITICAL_SECTION* cs = new(std::nothrow) CRITICAL_SECTION; if(!cs) return -1; p_lock = cs; InitializeCriticalSection(cs); } void lockTest::destroy() { if(!p_lock) return; cs = p_lock; DeleteCriticalSection(cs); delete cs; cs = NULL; p_lock = NULL; } void lockTest::lockStart() { if(p_lock) return; EnterCriticalSection(p_lock); } void lockTest::lockEnd() { if(p_lock) return; LeaveCriticalSection(p_lock); } bool lockTest::lockTry() { if(!p_lock) return false; if(!TryEnterCriticalSection(p_lock) return false; return true; }
<참고>
위 lockTest라는 클래스는..
자원이 존재하는 다른 클래스에서 맴버변수로 lockTest 를 선언 해놓고 사용할 수 있다.
코드에서 유추 할 수 있듯이..
하나의 lock 포인터를 공유하는 자원끼리 lock에 대한 공유가 가능하다..
-> 공유하는 자원이란.. 동일한 락을 사용하는 자원이라는 말이다.
-> 예제 코드를 보며 더 이해 해보자..
/////////////// 헤더파일 class Z { func1(); func2(); lockTest lockA; } /////////////// cpp 파일 Z::func1() { lockA.lockStart(); } Z::func2() { lockA.lockStart(); }
서로 다른 스레드에서 Z클래스의 동일한 인스턴스에서 func1, func2 함수를 호출 시,
서로 락의 영향이 생긴다.
참고1>
-> Z클래스에 lockB라는 lockTest 변수가 생겼고.. func2함수에서 lockB에 대한 lockStart 함수를 호출한다고 가정해보자..
-> 서로다른 스레드에서 func1, func2 함수를 호출 하는 것은 아무런 영향이 없다.
-> 왜냐하면.. lockTest의 실질적인 p_lock 변수가 .. 서로 다른 포인터이기 때문이다.
참고2>
-> Class Z말고 Class X에 lockTest 변수가 있는데.. X와 Z의 lockTest 변수가 포인터로 선언되어있으며
(lockTest 얕은 복사 관점 추가 구현 필요..)
-> 동일하다면... 다른 클래스라 할지라도 lock 포인터를 공유하기 때문에 서로 영향이 생긴다.
결국..
같은 lock 이냐가 중요하며.. lockStart가 현재 걸려있냐 아니냐에 따라 의미가 생긴다.
linux와 cross compile
window 버전을 조금 더 리뉴얼 해보자..
pthread.h 헤더파일을 사용한다.
/////////////// 헤더 파일 class lockTest { 함수 선언 생략.. void* p_lock; } /////////////// cpp 파일 lockTest::lockTest() { p_lock = NULL; initialize(); } lockTest::~lockTest() { destroy(); } int lockTest::initialize() { #ifdef _MSC_VER CRITICAL_SECTION* cs = new(std::nothrow) CRITICAL_SECTION; if(!cs) return -1; p_lock = (void*)cs; InitializeCriticalSection(cs); #else pthread_mutex_t* pm = new(std::nothrow) pthread_mutex_t; p_lock = (void*)pm; pthread_mutexattr_t pma; pthread_mutexattr_init(&pma); pthread_mutex_init(pm, &pma); #endif return 0; } void lockTest::destroy() { if(!p_lock) return; #ifdef _MSC_VER CRITICAL_SECTION* cs = (CRITICAL_SECTION*)p_lock; DeleteCriticalSection(cs); delete cs; cs = NULL; #else pthread_mutex_t* pm = (pthread_mutex_t*)p_lock; pthread_mutex_destroy(pm); delete pm; pm = NULL; #endif p_lock = NULL; } void lockTest::lockStart() { if(p_lock) return; #ifdef _MSC_VER EnterCriticalSection((CRITICAL_SECTION*)p_lock); #else pthread_mutex_lock((pthread_mutex_t*)p_lock); #endif } void lockTest::lockEnd() { if(p_lock) return; #ifdef _MSC_VER LeaveCriticalSection((CRITICAL_SECTION*)p_lock); #else pthread_mutex_unlock((pthread_mutex_t*)p_lock); #endif } bool lockTest::lockTry() { if(!p_lock) return false; #ifdef _MSC_VER if(!TryEnterCriticalSection(p_lock) return false; #else if(pthread_mutex_trylock((pthread_mutex_t*)p_lock) != 0) return false; #endif return true; }
cross compile을 위하여..
p_lock 의 자료형 변경과 전처리기를 이용하였다.
뮤텍스 락을 사용한다.
'C++' 카테고리의 다른 글
[Effective Modern C++] 항목 8 (0) 2022.08.14 [Effective Modern C++] 항목 5 (0) 2022.08.14 [C++] move와 copy (0) 2022.07.15 [C++] Template Type check (0) 2022.07.15 정적 vs 동적 링크 라이브러리 (0) 2022.04.03 다음글이전글이전 글이 없습니다.댓글