2015-01-20 7 views
1

POSIX 세마포어를 사용하여 C에서 스레드 안전 읽기/쓰기 잠금을 쓰려고합니다. 소스 코드 here의 현재 상태를 볼 수 있습니다. 독자가 선호하는 자물쇠를 만들기 위해 this을 추적했습니다.C에서 읽기 - 쓰기 잠금 스레드 안전 파괴 파괴

문제는 내가 rwl_destroy()가 호출 될 때있을 수있는 가능한 상태에 대한 잠금의 파괴를 처리하고자하는 것입니다. 만약 파괴

호출하고 다른 스레드가 다음 잠금 지키고 데이터에 액세스하는 다른 스레드를 방지하기 위해 (작가에 의해 사용됨) WRT를 잠급니다 잠금에 없습니다. 다음에는 destroy 함수가 세마포어를 없애고 ReadWriteLock 구조체에 할당 된 메모리를 해제해야합니다. 하지만 다른 스레드가 현재 잠금을 기다리고 있다면 어떻게 될까요? 문서에 따르면이 스레드는 정의되지 않은 상태로 남습니다.

그건 내가 잠금 장치를 사용하기 쉽게하기 위해 피하려고하는 것입니다.

편집 :

현재 코드는 다음과 같습니다

typedef struct ReadWriteLock 
{ 
sem_t wrt; 
sem_t mtx; 
sem_t delFlag; 
int readcount; 
int active; 
}ReadWriteLock; 

//forward declaration 
/* This function is used to take the state of the lock. 
* Return values: 
*  [*] 1 is returned when the lock is alive. 
*  [*] 0 is returned when the lock is marked for delete. 
*  [*] -1 is returned if an error was encountered. 
*/ 
int isActive(ReadWriteLock*); 

int rwl_init(ReadWriteLock* lock) 
{ 
lock = malloc(sizeof(ReadWriteLock)); 
if (lock == NULL) 
{ 
    perror("rwl_init - could not allocate memory for lock\n"); 
    return -1; 
} 
if (sem_init(&(lock->wrt), 0, 1) == -1) 
{ 
    perror("rwl_init - could not allocate wrt semaphore\n"); 
    free(lock); 
    lock = NULL; 
    return -1; 
} 
if (sem_init(&(lock->mtx), 0, 1) == -1) 
{ 
    perror("rwl_init - could not allocate mtx semaphore\n"); 
    sem_destroy(&(lock->wrt)); 
    free(lock); 
    lock = NULL; 
    return -1; 
} 
if (sem_init(&(lock->delFlag), 0 , 1) == -1) 
{ 
    perror("rwl_init - could not allocate delFlag semaphore\n"); 
    sem_destroy(&(lock->wrt)); 
    sem_destroy(&(lock->mtx)); 
    free(lock); 
    lock = NULL; 
    return -1; 
} 

lock->readcount = 0; 
lock->active = 1; 
return 0; 
} 

int rwl_destroy(ReadWriteLock* lock) 
{ 
errno = 0; 
if (sem_trywait(&(lock->wrt)) == -1) 
    perror("rwl_destroy - trywait on wrt failed."); 
if (errno == EAGAIN) 
    perror("rwl_destroy - wrt is locked, undefined behaviour."); 

errno = 0; 
if (sem_trywait(&(lock->mtx)) == -1) 
    perror("rwl_destroy - trywait on mtx failed."); 
if (errno == EAGAIN) 
    perror("rwl_destroy - mtx is locked, undefined behaviour."); 

if (sem_destroy(&(lock->wrt)) == -1) 
    perror("rwl_destroy - destroy wrt failed"); 
if (sem_destroy(&(lock->mtx)) == -1) 
    perror("rwl_destroy - destroy mtx failed"); 
if (sem_destroy(&(lock->delFlag)) == -1) 
    perror("rwl_destroy - destroy delFlag failed"); 

free(lock); 
lock = NULL; 
return 0; 
} 

int isActive(ReadWriteLock* lock) 
{ 
errno = 0; 
if (sem_trywait(&(lock->delFlag)) == -1) 
{ 
    perror("isActive - trywait on delFlag failed."); 
    return -1; 
} 
if (errno == EAGAIN) 
{//delFlag is down, lock is marked for delete 
    perror("isActive - tried to lock but ReadWriteLock was marked for delete"); 
    return 0; 
} 
return 1; 
} 

나는 또한 이러한 기능이 있습니다

int rwl_writeLock(ReadWriteLock*); 

int rwl_writeUnlock(ReadWriteLock*); 

int rwl_readLock(ReadWriteLock*); 

int rwl_readUnlock(ReadWriteLock*); 

그래서 제 질문은 당신이 정의를 피하기 위해이 기능을 변경하는 방법입니다 상태 I. ReadWriteLock을 파괴하기 전에이 코드의 사용자가 모든 잠금을 해제 할 책임이 있습니까?

이 isActive() 함수와 delFlag 세마포어

그들은 문제를 해결하기 위해 내 시도에서 만들어진, 현재 사용되지 않습니다. 당신은 당신의하는 ReadWriteLock 인스턴스의 "배치"상태를 구현해야

+0

질문에 문제가있는 코드를 포함하십시오. 링크가 끊어지면 문제는 문맥없이 여기에 있습니다. – xxbbcc

+0

이것은 평생 관리 문제입니다. 프로그램이 파괴 된 후 객체를 사용하면 일반적으로 버그라고합니다. –

+0

@xxbbcc 코드를 게시 할 수는 있지만 도움이 될 것이라고 생각하지 않습니다. 문제는 이론적입니다. 내 질문을 업데이트 할게. – JasonPap

답변

0

는 ("활성"필드는 적절한 보이지만, 왜 그것을 사용하지 않는?).

은 이전과 sem_wait() 호출 후, rwl_writeLock/rwl_readLock에 두 번 확인합니다. 이 트릭은 "이중 확인 잠금 패턴"으로 잘 알려져 있습니다. sem_wait에 들어가기 전에 Lock이 지워지는 것을 발견하면, 함수를 그대로 두십시오. sem_wait을 입력 한 후 잠금을 삭제 한 경우 sem_post를 즉시 수행하고 종료하십시오. 당신의 파괴() 루틴에서

, 활성 설정 = 0, 다음 sem_post 모두 세마포어에 (sem_post가 실패하면 귀찮게하지 않습니다). 나중에 sem_destroy가 필요하다면, 약간의 시간을 들여서 (따라서 모든 독자와 작성자는 신호를받을 시간이 있습니다) sem_destroy를 수행하십시오.

P. 세마포어를 더 이상 사용하지 않는다고 확신하는 경우 실제로 sem_destroy를 호출 할 필요가 없습니다.

+0

sleep()과의 동기화는 널리 알려진 반 패턴입니다. –

+0

@NickZavaritsky : 동적으로 힙에 할당되고 임의의 순간에 파괴되도록 설계된 rwlock의 자체 작성 구현 ... 예, 반 패턴을 고려해야 할 올바른 장소입니다. 당신은 정말로 OP가 작업 스레드의 파괴를 동기화 할 수있게 해주는 좋은 마무리 루틴을 가지고 있다고 생각하십니까? OK ... 묻지 말아야합니다 ... –

+0

@NickZavaritsky 왜 당신이 sleep()을 사용하는지 알 수 있습니다. 그러나 대신에 당신은 무엇을 제안합니까? 나는 아직도 Yury 제안에 관하여 틀린 무언가를 생각할 수 없다. 그러나 나는 다른 의견을보기 위해 붙들고있다. – JasonPap