gpt4 book ai didi

c - 在没有互斥锁的情况下,多线程仅初始化和反初始化一次

转载 作者:行者123 更新时间:2023-11-30 16:28:13 26 4
gpt4 key购买 nike

我有两个函数initialize()和deinitialize(),每个函数应该只运行一次。结构类似于:

int *x;

initialize()
{
x = malloc(sizeof(int) * 10);
}

deinitialize()
{
free(x);
}

如何确保只有第一个线程调用初始化并且只有最后一个线程调用去初始化。不使用互斥体可以实现这一点吗?

更新:抱歉信息贫乏。我实际上正在修改一个包含函数initialize() 和deinitialize() 的库。我需要使这两个函数线程安全。用户可能使用多个线程,并且可能多次调用这些函数。我不能假设用户将调用一次来初始化和取消初始化函数。我只能假设,如果一个线程调用初始化,它会在某个时刻调用去初始化。

用户将使用 pthread 库来创建不同的线程。

最佳答案

我不知道你想要实现什么,最简单的是:

#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() 仅调用一次。 id 为 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 可以在同一时刻同时执行(并行和并发)

关于c - 在没有互斥锁的情况下,多线程仅初始化和反初始化一次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52449575/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com