0

我编译了这段代码,它创建的第 99 个线程不断创建多个编号为 99 的线程。相反,如果我插入 1-10 或较小的值,那么结果是非常正常的。

这是代码。

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

pthread_mutex_t m=PTHREAD_MUTEX_INITIALIZER;
pthread_attr_t attr;

void* test(void *a)
{
    int i=*((int *)a);
    printf("The thread %d has started.\n",i);
    pthread_mutex_lock(&m);
    usleep(10000);
    printf("The thread %d has finished.\n",i);
    pthread_mutex_unlock(&m);
    pthread_exit(NULL);

}

int main()
{
    int i=0,j=0;
    pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE);
    pthread_t thread[100];

    for (i=0;i<100;i++)
    {
        j=i;
        pthread_create(&thread[i],&attr,test,&j);

    }

    for (i=0;i<100;i++)
        pthread_join(thread[i],NULL);
    return 0;
}

我得到:

..../*Normal Results*/
The thread 99 has finished.
The thread 99 has finished.
The thread 99 has finished.
The thread 99 has finished.
The thread 99 has finished.
The thread 99 has finished.

为什么会这样?

4

4 回答 4

1

每个线程都被传递给主线程中相同的堆栈位置 ( j)。如果没有进一步的同步,每个线程将被调度并j在打印其值之前运行和访问的时间是不确定的。

有很多方法可以从每个线程中打印出一个唯一的数字,包括

  1. malloc 一个在主线程中包含(或者是)这个数字的结构。将其传递给负责释放它的子线程
  2. (下面由 Brian Roche 建议)声明一个包含 100 个整数的数组,其值为 0、1、2 等。将不同数组项的地址传递给每个线程。
  3. 让每个线程锁定一个互斥锁,然后复制/增加一个全局计数器。互斥锁可以传递到线程或另一个全局
  4. 将信号量传递给每个线程,在访问该数字后发出信号。在主线程中等待这个信号量

请注意,选项 3 和 4 涉及线程的序列化启动。如果你做了很多这样的事情,那么运行多个线程就没有什么意义了!

于 2013-01-03T20:13:15.113 回答
1

您需要保留所有的 theadIds

int indexes[PTHREAD_COUNT];

for (i=0;i<100;i++) {
    indexes[i] = i;
    pthread_create(&thread[i], &attr, test, &indexes[i]);
}
于 2013-01-03T20:17:17.650 回答
0

i与您的主代码中的地址相同j,并且您在线程中休眠了 30 毫秒。所以所有线程都有时间运行,直到第一次互斥调用,然后它们都停止(稍微多一点)30ms,然后打印它们已经完成。当然,i在主循环中现在是 99,因为您已经完成了 pthread_join 循环。

您需要有一个“j”值数组[假设您希望所有线程独立运行]。或者做点别的。这一切都取决于你真正想要做什么。

于 2013-01-03T20:19:21.697 回答
0

您正在传递与指向数据 a 的指针相同的内存位置 (&j)。

当线程启动时,它们打印出刚刚分配给 j 的值,看起来没问题

但随后只有一个得到锁并进入睡眠状态,所有其他人都因此被封锁。当噩梦结束时,内存位置“a”当然有一个 int 值 99。

于 2013-01-03T20:20:14.510 回答