C에서 thread_local 변수 사용
이 기사에서는 C에서thread_local
변수를 사용하는 방법에 대한 몇 가지 방법을 설명합니다.
_Thread_local
유형을 사용하여 스레드 저장 기간으로 변수 선언
C 언어는auto
,static
,register
,extern
과 같은 다른 스토리지 클래스에 대해 여러 키워드를 정의합니다. C11 표준 사양 이후_Thread_local
지정자가 추가되었습니다. _Thread_local
저장 기간은 스레드 생성 순간에 시작되어 종료로 끝납니다. _Thread_local
객체에 저장된 값은 스레드가 시작될 때 초기화되고 스레드가 종료되면 정리됩니다. 일반적으로 스레드 로컬 개체는 공유 리소스의 경쟁 조건을 피하기위한 또 다른 대안입니다. 즉,_Thread_local
자격을 갖춘 객체가 각 스레드에 대해 별도의 인스턴스를 가지므로 스레드간에 데이터를 암시 적으로 분리합니다.
#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
#include <threads.h>
#ifndef NUM_THREADS
#define NUM_THREADS 4
#endif
_Thread_local int counter = 0;
enum { MAX_ITER = 10000 };
void *incrementCounter(void *thr_id) {
long tid;
tid = (long)thr_id;
printf("thread %ld started incrementing ID - %lu\n", tid, thrd_current());
for (int i = 0; i < MAX_ITER; ++i) {
counter += 1;
}
return (void *)counter;
}
int main(int argc, char const *argv[]) {
thrd_t threads[NUM_THREADS];
int rc, sum = 0;
for (int i = 0; i < NUM_THREADS; ++i) {
rc = thrd_create(&threads[i], (thrd_start_t)incrementCounter, (void *)i);
if (rc == thrd_error) {
printf("ERORR; thrd_create() call failed\n");
exit(EXIT_FAILURE);
}
}
int retval;
for (int i = 0; i < NUM_THREADS; ++i) {
thrd_join(threads[i], &retval);
sum += retval;
}
printf("count = %d\n", sum);
thrd_exit(EXIT_SUCCESS);
}
출력:
thread 1 started incrementing ID - 140162648991488
thread 0 started incrementing ID - 140162657384192
thread 2 started incrementing ID - 140162640598784
thread 3 started incrementing ID - 140162632206080
count = 40000
thread_local
유형을 사용하여 스레드 저장 기간으로 변수 선언
또는 C 언어는 지정자를_Thread_local
로 표시하기 위해 매크로 표현식thread_local
을 정의합니다. thread_local
변수는 모든 스레드가 볼 수 있도록 파일 범위에서 선언되어야합니다. 그렇지 않으면 사용자가static
지정자를 명시 적으로 추가하여 범위를 파일 레벨로 확장 할 수도 있습니다. 스레드가thread_local
오브젝트의 값을 메인 스레드에 전달해야하므로 프로그램 구조를 수정해야합니다. 단순 카운터 프로그램을 구현하는 이전 예제 코드는 증가 된 카운터 값을 호출 스레드로 다시 전달하도록 수정해야합니다. 따라서thrd_join
함수와 스레드 루틴의 반환 값을 저장하는 두 번째 인수를 사용해야합니다. 증가 된 모든 값은 메인 스레드에서 합산되어야하며, 이는 최종 결과를stdout
에 인쇄하는 역할도 담당합니다.
#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
#include <threads.h>
#ifndef NUM_THREADS
#define NUM_THREADS 4
#endif
thread_local int counter = 0;
enum { MAX_ITER = 10000 };
void *incrementCounter(void *thr_id) {
long tid;
tid = (long)thr_id;
printf("thread %ld started incrementing ID - %lu\n", tid, thrd_current());
for (int i = 0; i < MAX_ITER; ++i) {
counter += 1;
}
return (void *)counter;
}
int main(int argc, char const *argv[]) {
thrd_t threads[NUM_THREADS];
int rc, sum = 0;
for (int i = 0; i < NUM_THREADS; ++i) {
rc = thrd_create(&threads[i], (thrd_start_t)incrementCounter, (void *)i);
if (rc == thrd_error) {
printf("ERORR; thrd_create() call failed\n");
exit(EXIT_FAILURE);
}
}
int retval;
for (int i = 0; i < NUM_THREADS; ++i) {
thrd_join(threads[i], &retval);
sum += retval;
}
printf("count = %d\n", sum);
thrd_exit(EXIT_SUCCESS);
}
출력:
thread 1 started incrementing ID - 140162648991488
thread 2 started incrementing ID - 140162640598784
thread 0 started incrementing ID - 140162657384192
thread 3 started incrementing ID - 140162632206080
count = 40000
Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.
LinkedIn Facebook