简体   繁体   English

POSIX线程同步和/或pthread_create()参数传递出现问题

[英]Issue with POSIX thread synchronization and/or pthread_create() argument passing

I am trying to create a number of different threads that are required to wait for all of the threads to be created before they can perform any actions. 我正在尝试创建许多不同的线程,这些线程需要等待所有线程创建后才能执行任何操作。 This is a smaller part of a large program, I am just trying to take it in steps. 这只是大型程序的一小部分,我只是试图逐步进行。 As each thread is created it is immediately blocked by a semaphore. 创建每个线程时,它会立即被信号量阻塞。 After all of the threads have been created, I loop through and release all the threads. 创建所有线程之后,我循环浏览并释放所有线程。 I then wish each thread to print out its thread number to verify that they all waited. 然后,我希望每个线程都打印出其线程号以验证它们是否都已等待。 I only allow one thread to print at a time using another semaphore. 我只允许使用另一个信号灯一次打印一个线程。

The issue I'm having is that although I create threads #1-10, a thread prints that it is #11. 我遇到的问题是,尽管我创建了线程#1-10,但有一个线程打印出它是#11。 Also, a few threads say they have the same number as another one. 另外,一些线程表示它们与另一个线程具有相同的编号。 Is the error in my passing the threadID or is it in my synchronization somehow? 是我传递threadID时出错还是以某种方式在同步中?

Here is relevant code: 以下是相关代码:

//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);
    }

When T_Valve_Numbers = 10, some sample output is: 当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?

OR 要么

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

"I'm thread..." is printing 10 times so it appears like my semaphore is letting all of the threads through. “我是线程...”正在打印10次,因此看来我的信号量让所有线程都通过了。 I'm just not sure why their thread number is messed up. 我只是不确定为什么他们的线程号搞砸了。

check=pthread_create(&threads[i], NULL, Valve_Handler,(void*)&i);
                                                             ^^

You're passing the thread start function the address of i . 您正在向线程启动函数传递i的地址。 i is changing all the time in the main loop, unsynchronized with the thread functions. i一直在改变主循环中的所有时间,与线程功能不同步。 You have no idea what the value of i will be once the thread function gets around to actually dereferencing that pointer. 您不知道一旦线程函数实际取消对该指针的引用, i的值将是多少。

Pass in an actual integer rather than a pointer to the local variable if that's the only thing you'll ever need to pass. 如果这是您唯一需要传递的内容,则传递一个实际的整数而不是指向局部变量的指针。 Otherwise, create a simple struct with all the parameters, build an array of those (one for each thread) and pass each thread a pointer to its own element. 否则,请创建一个具有所有参数的简单struct ,构建一个包含这些参数的数组(每个线程一个),然后将每个线程的指针传递给它自己的元素。

Example: (assuming your thread index never overflows an int ) 示例:(假设您的线程索引永远不会溢出int

#include <stdint.h> // for intptr_t

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

int threadNum = (intptr_t)threadNumArg;

Better/more flexible/doesn't require intprt_t that might not exist example: 更好/更灵活/不需要不需要的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

A word of caution about this though: that array of thread arguments needs to stay alive at least as long as the threads will use it. 不过请注意:线程参数数组至少要在线程将使用它的情况下保持有效。 In some situations, you might be better of with a dynamic allocation for each structure, passing that pointer (and its ownership) to the thread function (especially if you're going to detach the threads rather than joining them). 在某些情况下,最好为每个结构进行动态分配,将该指针(及其所有权)传递给线程函数(尤其是如果要分离线程而不是加入线程的话)。

If you're going to join the threads at some point, keep those arguments around the same way you keep your pthread_t structures around. 如果您打算在某个时候加入线程,则保留这些参数的方式与保留pthread_t结构的方式相同。 (And if you're creating and joining in the same function, the stack is usually fine for that.) (如果您要创建并加入相同的函数,则通常可以使用堆栈。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM