简体   繁体   中英

Duplicated thread ID in pthread_create between loop?

I have a loop and each iteration of the loop will create 5 threads with pthread_create. I noticed there are duplicates of thread IDs not within the same loop, but between loops. Is this correct as i'm expecting all the thread IDs should be unique?

Here are the sample code,

#include <pthread.h>
#define NTHREADS1 5
void maintest()
{
    loopCreate();

}
void loopCreate()
{

 for(int index=0; index<2; index++)
 {
    int i;
    int j;
    pthread_t thread_id[NTHREADS1];
    for(i=0; i < NTHREADS1; i++)
   {
      pthread_create( &thread_id[i], NULL, thread_function, NULL );
      cout<<"threadcnt="<<i<<"; "<<"thread_id=" << thread_id[i] << endl;
   }

    for(j=0; j < NTHREADS1; j++)
   {
      pthread_join( thread_id[j], NULL); 
   }
 }  
}

void *thread_function(void *dummyPtr)
{
  int j;
  int jcounter;
  jcounter =0;
  pthread_t threadId;
  threadId = pthread_self();
  cout<<"Thread_number="<<threadId<<endl;

  return NULL;
}

And here is output trace and as you can see, there are duplicate thread IDs between loop 1 and loop 2

//Loop 1
threadcnt=0; thread_id=2061794160
Thread_number=2061794160
threadcnt=1; thread_id=2264922992
Thread_number=2264922992
threadcnt=2; thread_id=2162469744
Thread_number=2162469744
threadcnt=3; thread_id=2128911216
Thread_number=2128911216
Thread_number=2095352688
threadcnt=4; thread_id=2095352688

//Loop 2
threadcnt=0; thread_id=2095352688
Thread_number=2095352688
threadcnt=1; thread_id=2264922992
Thread_number=2264922992
threadcnt=2; thread_id=2162469744
Thread_number=2162469744
threadcnt=3; thread_id=2128911216
Thread_number=2128911216
Thread_number=2061794160
threadcnt=4; thread_id=2061794160

Edit: for a more in-depth discussion on the structure of pthread_t please see @Alexander Schwartz's answer.

You are joining the threads at the end of each iteration. From https://linux.die.net/man/3/pthread_self we can see:

[...] A thread ID may be reused after a terminated thread has been joined, or a detached thread has terminated.

So the OS is free of reusing ids of terminated (in your case joined) threads.

Furthermore from https://linux.die.net/man/7/pthreads

Each of the threads in a process has a unique thread identifier (stored in the type pthread_t). This identifier is returned to the caller of pthread_create(3), and a thread can obtain its own thread identifier using pthread_self(3).

So you are guaranteed to have uniqueness of IDs only on the set of running threads of a process.

There is no way bug free code could ever tell if a pthread_t is reused. Your code has a bug:

  cout<<"threadcnt="<<i<<"; "<<"thread_id=" << thread_id[i] << endl;

Nothing specifies what the printed value of a pthread_t should be. It may or may not include the entire value of the pthread_t . Every one could print as zero. You cannot assume it means anything at all.

This code could even crash. The output routine could try to access bytes in the pthread_t that are not mapped into memory. The behavior of this code is entirely undefined. On your platform, pthread_t might behave like char * and this code might attempt to dereference it, but it may not point to any valid object. Who knows? The standard makes pthread_t an entirely opaque type with only a very limited set of defined operations.

The standard explicitly permits a pthread_t to be a struct . So the standard doesn't even require this code to compile. It is unreasonable to expect a meaningful value.

You might think that you can do it by comparing the pthread_t s for equality rather than printing them. But you cannot. The only permitted way to compare pthread_t s for equality is with pthread_equal but the documentation says, " If either t1 or t2 are not valid thread IDs, the behavior is undefined. " and since the thread has terminated and been joined, it's ID is no longer valid.

It is literally impossible for a thread ID to be duplicated because the two thread IDs do not have any overlap in their lifetime and there is no meaningful value to the thread ID that persists beyond its lifetime. A thread ID is just an opaque reference to a thread while that thread has not been joined or terminated and detached. It has no numerical value. The actual bytes of memory may contain extraneous bytes, indirect references, or anything else. The pthreads standard explicitly says you may not manipulate a thread ID in this way.

If you need a thread ID that has different semantics, there are lots of ways you can get one. But that would not be pthread_t .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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