반응형
스레드에서 clock함수 사용 시 발생하는 문제
스레드를 여러개 만들고 각 스레드에 시간 함수인 clock을 사용하면 시간이 이상 출력될 수 있다. 예를 들어 pthread를 이용하여 만든 스레드가 두 개일 경우 시간이 두배로 흘러가고 세 개일 경우 세배로 흘러간다.
이는 clock함수가 프로세스 클록 횟수를 이용하여 시간을 얻어오는데, 스레드끼리 클록 횟수를 공유하여 스레드가 호출될 떄마다 프로세스 클록이 증가하는 것으로 보인다.
clock 대신 clock_gettime 사용
clock 대신 clock_gettime함수를 사용하여 위 문제를 해결할 수 있다. clock_gettime함수는 CLOCK_REALTIME과 CLOCK_MONOTINIC 방식 중 선택하여 시간을 얻어올 수 있는데, CLOCK_REALTIME은 시스템 시간을 얻어오므로 시스템 시간이 변경되면 수행 시간이 변경되는 문제가 있다. 따라서 특정 시점으로부터 흐르는 시간을 호출하는 CLOCK_MONOTONIC 방식을 사용한다.
예제 코드
- 테스트환경 : Ubuntu 20.04 / C / gcc
- 예제는 pthread를 이용하여 구현되었다. pthread의 사용법은 아래 글을 참고할 수 있다.
2021/03/08 - [언어, 라이브러리/C, C++] - [C, C++] Pthread로 스레드 구현 - 예제는 약 1초마다 한 번씩 스레드 A와 B가 호출되며, 스레드 A와 B는 수행 시간을 출력한다.
clock을 사용한 코드
스레드A와 B가 약 0.5초에 한 번씩 호출된다.
#include <pthread.h>
#include <stdio.h>
#include <stdint.h>
#include <time.h>
void *threadA()
{
clock_t timeBegin, timeEnd;
uint8_t intTime = 0;
double currentTime = 0;
timeBegin = clock();
while(1)
{
timeEnd = clock();
currentTime = (double)(timeEnd-timeBegin)/CLOCKS_PER_SEC;
if(currentTime > intTime)
{
intTime++;
printf("thread A %f\n", currentTime);
}
}
}
void *threadB()
{
clock_t timeBeginB, timeEndB;
uint8_t intTime = 0;
double currentTime = 0;
timeBeginB = clock();
while(1)
{
timeEndB = clock();
currentTime = (double)(timeEndB-timeBeginB)/CLOCKS_PER_SEC;
if(currentTime > intTime)
{
intTime++;
printf("thread B %f\n", currentTime);
}
}
}
int main()
{
printf("hello world\n");
pthread_t tA, tB;
uint8_t threadReturn = 0;
threadReturn = pthread_create(&tA, NULL, threadA, NULL);
if(threadReturn != 0)
{
printf("thread A create fail : %d\n", threadReturn);
}
threadReturn = pthread_create(&tB, NULL, threadB, NULL);
if(threadReturn != 0)
{
printf("thread B create fail : %d\n", threadReturn);
}
threadReturn = pthread_join(tA, NULL);
if(threadReturn != 0)
{
printf("thread A join fail\n");
}
threadReturn = pthread_join(tB, NULL);
if(threadReturn != 0)
{
printf("thread B join fail\n");
}
return 0;
}
clock_gettime을 사용한 코드
스레드 A와 B가 약 1초에 한 번씩 호출된다.
#include <pthread.h>
#include <stdio.h>
#include <stdint.h>
#include <time.h>
void *threadA()
{
struct timespec timeBegin, timeEnd;
uint8_t intTime = 0;
double currentTime = 0;
clock_gettime(CLOCK_MONOTONIC, &timeBegin);
while(1)
{
clock_gettime(CLOCK_MONOTONIC, &timeEnd);
currentTime = timeEnd.tv_sec - timeBegin.tv_sec;
if(currentTime > intTime)
{
intTime++;
printf("thread A %f\n", currentTime);
}
}
}
void *threadB()
{
struct timespec timeBegin, timeEnd;
uint8_t intTime = 0;
double currentTime = 0;
clock_gettime(CLOCK_MONOTONIC, &timeBegin);
while(1)
{
clock_gettime(CLOCK_MONOTONIC, &timeEnd);
currentTime = timeEnd.tv_sec - timeBegin.tv_sec;
if(currentTime > intTime)
{
intTime++;
printf("thread B %f\n", currentTime);
}
}
}
int main()
{
printf("hello world\n");
pthread_t tA, tB;
uint8_t threadReturn = 0;
threadReturn = pthread_create(&tA, NULL, threadA, NULL);
if(threadReturn != 0)
{
printf("thread A create fail : %d\n", threadReturn);
}
threadReturn = pthread_create(&tB, NULL, threadB, NULL);
if(threadReturn != 0)
{
printf("thread B create fail : %d\n", threadReturn);
}
threadReturn = pthread_join(tA, NULL);
if(threadReturn != 0)
{
printf("thread A join fail\n");
}
threadReturn = pthread_join(tB, NULL);
if(threadReturn != 0)
{
printf("thread B join fail\n");
}
return 0;
}
최근댓글