正在创建具有重复 ID 的 Pthread

Pthreads are being created with duplicate ID's

我正在使用线程来模拟许多想要预订威胁座位的客户。每个客户(线程)都应该有一个唯一的 ID,并且每个线程都通过一个结构接收一些数据(该 ID 包含在结构内的数据中)。问题是当我执行代码时某些线程具有相同的 ID,我想知道这是怎么发生的,因为为了创建一个线程,for 循环的另一次迭代需要发生,这样, thread_id 在将结构传递给新线程并创建下一个线程之前用另一个值更新。

谁能帮我理解为什么会出现重复值以及如何解决这个问题?谢谢!

int main(int argc, char *argv[])
{
    ThreadData threadData; //the struct which is used as input in the 
    // thread_transaction method, contains the id and other thread 
    //information
    pthread_t* thread_ids = (pthread_t*)malloc(sizeof(pthread_t) * 
    n_cust);

    for(i = 0; i < n_cust; i++){
        threadData.thread_id = i;
        pthread_create(&thread_ids[i], NULL, &thread_transaction, (void *) 
        (&threadData));
    }

    for(j=0; j < n_cust; j++) {
        pthread_join(thread_ids[j], NULL);
    }
    printf("SEAT ARRANGEMENT: \n");
    for(y=0; y<Nseat;y++){
        printf("Seat %d / Costumer %d, ", y, threadData.seats_array[y]);
    }

    free(thread_ids);

    return 0;
  }


 void* thread_transaction(void* arg)
 {
   ThreadData* threadData = (ThreadData*) arg;
   pthread_mutex_lock(&id_mut); //i even tried mutex-locking the ID
   int id= threadData->thread_id;
   pthread_mutex_unlock(&id_mut);
  .
  .
  .
   printf("Your reservation is completed successfully. Your transaction 
   number is %d ", id); //for 5 customers eg. it printed 4 0 4 2 2
 }

I am wondering how is this happening since, in order for a thread to be created, another iteration of the for loop needs to happen and this way, the thread_id is updated with another value, before the struct is passed to the new thread and the next thread is created.

你刚刚回答了你自己的问题。是的,在循环的下一次迭代中,您更新呈现给前一个线程的同一结构的 thread_id。那么如果前一个线程还没有读取它的 ID 值,你认为会发生什么?答案:它可以读取下一个线程的值而不是它自己的值。

更一般地说,你有一个数据竞争,因为 thread_id 成员在主线程和它刚刚创建的线程之间共享,它们在没有适当同步的情况下访问它,* 并且其中一个访问是写入。包含数据竞争的程序具有未定义的行为,因此线程获取错误的 ID 是您最不用担心的。

您或许可以使用信号量在主线程和每个新线程之间提供所需的同步和排序,这样主线程就不会过早地或不安全地修改 threadData。但我认为为每个线程提供自己的单独 ThreadData 对象会更容易和更通用,无论是动态分配还是来自它们的普通数组。


*尽管新线程使用互斥体保护其访问,但这还不够。 所有 访问必须由相同的互斥锁保护,以提供正确的同步。此外,即使这样也不能确保写入和读取所需的相对顺序。