Как мне начать темы в простой C?
Я использовал fork() в C, чтобы начать другой процесс. Как начать новую тему?
6 ответов
Так как вы упомянули fork(), я предполагаю, что вы работаете в Unix-подобной системе, и в этом случае вам нужно использовать потоки POSIX (обычно называемые pthreads).
В частности, pthread_create() - это функция, необходимая для создания нового потока. Его аргументы:
int pthread_create(pthread_t * thread, pthread_attr_t * attr, void *
(*start_routine)(void *), void * arg);
Первый аргумент - это возвращенный указатель на идентификатор потока. Второй аргумент - это аргументы потока, которые могут иметь значение NULL, если вы не хотите запускать поток с определенным приоритетом. Третий аргумент - это функция, выполняемая потоком. Четвертый аргумент - это единственный аргумент, передаваемый функции потока при ее выполнении.
C11 темы
Добавлено в glibc 2.28. Протестировано в Ubuntu 18.04 (glibc 2.27) путем компиляции glibc из исходного кода: несколько библиотек glibc на одном хосте
Пример из: https://en.cppreference.com/w/c/language/atomic
#include <stdio.h>
#include <threads.h>
#include <stdatomic.h>
atomic_int acnt;
int cnt;
int f(void* thr_data)
{
for(int n = 0; n < 1000; ++n) {
++cnt;
++acnt;
// for this example, relaxed memory order is sufficient, e.g.
// atomic_fetch_add_explicit(&acnt, 1, memory_order_relaxed);
}
return 0;
}
int main(void)
{
thrd_t thr[10];
for(int n = 0; n < 10; ++n)
thrd_create(&thr[n], f, NULL);
for(int n = 0; n < 10; ++n)
thrd_join(thr[n], NULL);
printf("The atomic counter is %u\n", acnt);
printf("The non-atomic counter is %u\n", cnt);
}
Скомпилируйте и запустите:
gcc -std=c11 main.c -pthread
./a.out
Возможный вывод:
The atomic counter is 10000
The non-atomic counter is 8644
Неатомарный счетчик, вероятно, будет меньше атомного из-за быстрого доступа через потоки к неатомарной переменной.
ТОДО: разбери и посмотри что ++acnt;
компилируется в.
POSIX темы
#define _XOPEN_SOURCE 700
#include <assert.h>
#include <stdlib.h>
#include <pthread.h>
enum CONSTANTS {
NUM_THREADS = 1000,
NUM_ITERS = 1000
};
int global = 0;
int fail = 0;
pthread_mutex_t main_thread_mutex = PTHREAD_MUTEX_INITIALIZER;
void* main_thread(void *arg) {
int i;
for (i = 0; i < NUM_ITERS; ++i) {
if (!fail)
pthread_mutex_lock(&main_thread_mutex);
global++;
if (!fail)
pthread_mutex_unlock(&main_thread_mutex);
}
return NULL;
}
int main(int argc, char **argv) {
pthread_t threads[NUM_THREADS];
int i;
fail = argc > 1;
for (i = 0; i < NUM_THREADS; ++i)
pthread_create(&threads[i], NULL, main_thread, NULL);
for (i = 0; i < NUM_THREADS; ++i)
pthread_join(threads[i], NULL);
assert(global == NUM_THREADS * NUM_ITERS);
return EXIT_SUCCESS;
}
Скомпилируйте и запустите:
gcc -std=c99 pthread_mutex.c -pthread
./a.out
./a.out 1
Первый запуск работает нормально, второй отказывает из-за отсутствия синхронизации.
Проверено на Ubuntu 18.04. GitHub вверх по течению.
AFAIK, ANSI C не определяет потоки, но есть различные доступные библиотеки.
Если вы работаете в Windows, создайте ссылку на msvcrt и используйте _beginthread или _beginthreadex.
Если вы работаете на других платформах, проверьте библиотеку pthreads (я уверен, что есть и другие).
Потоки не являются частью стандарта C, поэтому единственный способ использовать потоки - это использовать некоторую библиотеку (например: потоки POSIX в Unix/Linux, _beginthread/_beginthreadex, если вы хотите использовать среду выполнения C из этого потока или просто CreateThread Win32 API)