【问题标题】:Issue with POSIX thread synchronization and/or pthread_create() argument passingPOSIX 线程同步和/或 pthread_create() 参数传递问题
【发布时间】:2014-10-19 15:55:06
【问题描述】:

我正在尝试创建许多不同的线程,这些线程需要等待所有线程被创建,然后才能执行任何操作。这是一个大型程序的一小部分,我只是想逐步进行。在创建每个线程时,它会立即被信号量阻塞。创建完所有线程后,我循环并释放所有线程。然后我希望每个线程都打印出它的线程号来验证它们是否都在等待。我只允许一个线程使用另一个信号量一次打印。

我遇到的问题是,虽然我创建了 #1-10 线程,但一个线程打印出它是 #11。此外,一些线程说它们与另一个线程具有相同的编号。是我传递 threadID 的错误还是我的同步中的错误?

这里是相关代码:

//Initialize semaphore to 0. Then each time a thread is spawned it will call
    //semWait() making the value negative and blocking that thread. Once all of the
    //threads are created, semSignal() will be called to release each of the threads
     sem_init(&threadCreation,0,0);


     sem_init(&tester,0,1);


    //Spawn all of the opener threads, 1 for each valve
    pthread_t threads[T_Valve_Numbers];
    int check;

    //Loop starts at 1 instead of the standard 0 so that numbering of valves
    //is somewhat more logical. 
    for(int i =1; i <= T_Valve_Numbers;i++)
    {
        cout<<"Creating thread: "<<i<<endl;
        check=pthread_create(&threads[i], NULL, Valve_Handler,(void*)&i);
        if(check)
        {
            cout <<"Couldn't create thread "<<i<<" Error: "<<check<<endl;
            exit(-1);
        }
    }

    //Release all of the blocked threads now that they have all been created
    for(int i =1; i<=T_Valve_Numbers;i++)
    {
        sem_post(&threadCreation);
    }

    //Make the main process wait for all the threads before terminating
    for(int i =1; i<=T_Valve_Numbers;i++)
    {
        pthread_join(threads[i],NULL);
    }
    return 0;



}   
    void* Valve_Handler(void* threadNumArg)
    {   
        int threadNum = *((int *)threadNumArg);
        sem_wait(&threadCreation);//Blocks the thread until all are spawned

        sem_wait(&tester);
        cout<<"I'm thread "<<threadNum<<endl;
        sem_post(&tester);
    }

当 T_Valve_Numbers = 10 时,一些样本输出为:

Creating thread: 1
Creating thread: 2
Creating thread: 3
Creating thread: 4
Creating thread: 5
Creating thread: 6
Creating thread: 7
Creating thread: 8
Creating thread: 9
Creating thread: 10
I'm thread 11   //Where is 11 coming from?
I'm thread 8
I'm thread 3
I'm thread 4
I'm thread 10
I'm thread 9
I'm thread 7
I'm thread 3
I'm thread 6
I'm thread 6   //How do I have 2 6's?

Creating thread: 1
Creating thread: 2
Creating thread: 3
Creating thread: 4
Creating thread: 5
Creating thread: 6
Creating thread: 7
Creating thread: 8
Creating thread: 9
Creating thread: 10
I'm thread 11
I'm thread 8
I'm thread 8
I'm thread 4
I'm thread 4
I'm thread 8
I'm thread 10
I'm thread 3
I'm thread 9
I'm thread 8 //Now '8' showed up 3 times

“我是线程...”打印了 10 次,所以看起来我的信号量让所有线程都通过了。我只是不知道为什么他们的线程数搞砸了。

【问题讨论】:

  • 将 I 的值而不是其地址传递给线程。
  • 正如我在下面所说的,我必须传递一个类型 void * 并且我的编译器不允许我直接从 int 转换。我找不到/想出任何其他方法。

标签: c++ multithreading semaphore


【解决方案1】:
check=pthread_create(&threads[i], NULL, Valve_Handler,(void*)&i);
                                                             ^^

您正在向线程启动函数传递i 的地址。 i 在主循环中一直在变化,与线程函数不同步。您不知道一旦线程函数开始实际取消引用该指针,i 的值将是什么。

如果这是你唯一需要传递的东西,则传递一个实际的整数而不是指向局部变量的指针。否则,使用所有参数创建一个简单的struct,构建一个包含这些参数的数组(每个线程一个),并为每个线程传递一个指向其自身元素的指针。

示例:(假设您的线程索引永远不会溢出int

#include <stdint.h> // for intptr_t

...
check = pthread_create(..., (void*)(intptr_t)i);
...

int threadNum = (intptr_t)threadNumArg;

更好/更灵活/不需要可能不存在的intprt_t 示例:

struct thread_args {
  int thread_index;
  int thread_color;
  // ...
}

// ...

struct thread_args args[T_Valve_Numbers];
for (int i=0; i<T_Valve_Numbers; i++) {
  args[i].thread_index = i;
  args[i].thread_color = ...;
}

// ...

check = pthread_create(..., &(args[i-1])); // or loop from 0, less surprising

对此请注意:线程参数数组至少需要在线程使用它时保持活动状态。在某些情况下,您可能会更好地为每个结构动态分配,将该指针(及其所有权)传递给线程函数(特别是如果您要分离线程而不是加入它们)。

如果您打算在某个时候加入线程,请保持这些参数与保持 pthread_t 结构的方式相同。 (如果你创建和加入同一个函数,堆栈通常就可以了。)

【讨论】:

  • 我花了大概 2 个小时试图让我传递给我的线程。 pthread_create 要求我给它一个 void* 类型,如果我尝试直接转换我的 int i,我会因为大小差异而出现编译错误。这是我让它不冲我大喊大叫的唯一方法
  • intptr_tvoid* 的大小相同,因此您可以在这种情况下使用它。 (或uintptr_t。)
  • 谢谢!那解决了它。希望我昨天花了这么多时间寻找时找到了那个解决方案。
猜你喜欢
  • 1970-01-01
  • 2011-09-22
  • 1970-01-01
  • 1970-01-01
  • 2013-04-20
  • 1970-01-01
  • 1970-01-01
  • 2010-12-13
  • 1970-01-01
相关资源
最近更新 更多