Я не знаю, чего вы хотите достичь, самое простое:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
int *x;
int running;
void initialization(void)
{
x = malloc(sizeof(int) * 10);
puts("First thread init x");
}
void deinitialization(void)
{
free(x);
puts("Last thread reset x");
}
void *handler(void *data)
{
printf("Thread started\n");
while (running) {
do_work();
}
printf("Thread exit\n");
}
int main(void)
{
pthread_t threads[3];
initialization();
for (int i = 0; i < 3; i++)
pthread_create(&threads[i], NULL, &handler, NULL);
sleep(2);
running = 0;
for (int i = 0; i < 3; i++)
pthread_join(threads[i], NULL);
deinitialization();
return 0;
}
Здесь вы можете быть уверены, что вы звонили init()
и deinit()
только один раз.
ОБНОВЛЕНИЕ
Другой вариант немного сложнее, но здесь вы также можете быть уверены, что init()
вызывается только один раз.Поток с идентификатором 0 может начинаться после 1, в этом случае нам следует подождать, пока *x
равно NULL.
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#define MAX_THREADS 3
int *x;
int running;
int init;
struct thread_info
{
pthread_t thread;
int id;
int first_id;
int last_id;
};
void initialization(void)
{
x = malloc(sizeof(int) * 10);
puts("First thread init x");
init = 1;
}
void deinitialization(void)
{
free(x);
puts("Last thread reset x");
}
void *handler(void *data)
{
struct thread_info *tinfo = data;
printf("Thread started\n");
if (tinfo->id == 0)
initialization();
while (!init);
/* EMPTY BODY */
while (running) {
do_work();
}
printf("Thread exit\n");
}
int main(void)
{
struct thread_info threads[MAX_THREADS] =
{
[0 ... 2].id = -1,
[0 ... 2].first_id = 0,
[0 ... 2].last_id = (MAX_THREADS - 1)
};
for (int i = 0; i < 3; i++)
pthread_create(&threads[i].thread, NULL, &handler,
((threads[i].id = i), &(threads[i])));
sleep(2);
running = 0;
for (int i = 0; i < 3; i++)
pthread_join(threads[i].thread, NULL);
deinitialization();
return 0;
}
deinit()
немного сложно, потому что ваш последний поток может завершиться, и free(x)
, пока другой поток все еще работает и, возможно, использует его.Поэтому я оставляю его после завершения всех потоков.
В этом и заключается смысл параллельного программирования.Вы никогда не можете делать какие-либо предположения о порядке выполнения потоков.
Точное время выполнения задач в параллельной системе зависит от планирования, и задачи не всегда должны выполняться одновременно.Например, если заданы две задачи, T1 и T2:
T1 могут быть выполнены и завершены до T2 или наоборот (последовательный и последовательный)
T1 и T2 могут выполняться поочередно (последовательный и одновременный)
T1 и T2 могут выполняться одновременно в один и тот же момент времени (параллельный и одновременный)