您似乎对线程的一般工作方式有些困惑。
实际上,thread_func()
不会在您创建的不同线程之间共享。每个线程都有自己的上下文;即使它们都在执行thread_func()
,只要一切都是本地的,它们中的任何一个都不会干扰另一个的计算。
唯一需要担心并发访问的情况是共享数据(例如全局变量)。在这种情况下,您通常使用互斥锁或信号量。阅读pthread_mutex_t
和sem_t
更新:由于您没有具体说明t
and i
,我认为它们是局部变量。如果它们是全局的,您必须使用互斥锁来同步访问这些变量。请记住,调用全局变量无意义的名称,例如t
ori
通常是不好的做法。
UPDATE2:通过您的编辑,我现在了解您真正想要什么。目前我能想到的唯一解决方案是你需要一个全局变量来t
为每个线程服务。让我们称之为step
。step
是全局的,因为每个线程都可以读取它并知道当前迭代是什么。然而,为了协调对这个变量的并发访问,我们需要一个互斥体,正如我之前提到的。
基本布局是这样的:线程存储在其上下文中执行的最后一次迭代。它正在反复测试step
以查看它是否被另一个线程更新。发生这种情况时,它开始执行for
循环(带有i = start; ...
. 的循环)在执行循环后,线程必须测试它是否是这次迭代的最后一个;如果是,它必须增加全局step
值发生时,任何等待新值的线程step
都会向前移动)。
测试我们是否是最后一个线程意味着您以某种方式知道您创建的线程数。您可以将其作为参数传递,或将其定义为常量。我假设它被定义为THREADS_NO
.
因此,我们还需要一个全局计数器和互斥锁来知道有多少线程已经结束了当前迭代
因此,您的文件将类似于:
pthread_mutex_t step_mutex;
pthread_mutex_t counter_mutex;
int step;
int counter;
void* thread_func(void* a) {
int t, i, curr_t;
struct type *b = (struct type*)a;
int start = b->start;
int stop = b->stop;
t = -1;
curr_t = 0;
while (1) {
while (curr_t == t) {
/* Wait for the next step */
pthread_mutex_lock(&step_mutex);
curr_t = step;
pthread_mutex_unlock(&step_mutex);
}
/* New value for t arrived */
t = curr_t;
if (t >= 1000) {
break;
}
for (i = start; i < stop; i++) {
/***** Calculation*****/
}
pthread_mutex_lock(&counter_mutex);
if (++counter == THREADS_NO) {
counter = 0;
pthread_mutex_lock(&step_mutex);
step++;
pthread_mutex_unlock(&step_mutex);
}
pthread_mutex_unlock(&counter_mutex);
}
return NULL;
}
您必须在创建任何线程之前初始化两个互斥锁,可能在 中main()
,使用:
pthread_mutex_init(&step_mutex, NULL);
pthread_mutex_init(&counter_mutex, NULL);
当你完成工作时,别忘了销毁它们:
pthread_mutex_destroy(&step_mutex);
pthread_mutex_destroy(&counter_mutex);
请注意,您应该测试初始化、锁定和销毁互斥锁的函数的返回值,因为可能会发生错误。
最后,考虑一下这是否是你真正想要的:也许你需要重新设计你的程序或算法。这种方法效率不高,因为线程会浪费 CPU 周期来重复测试新值step
(这称为忙等待)。很像“我们到了吗?我们到了吗?我们到了吗?”......不是很聪明。
注意:我无法测试此代码。您发布的代码使您很难知道您要实现的目标,因此我不确定这是否完全适合您。