'PThreads in C, how are thread-IDs generated, why they alternate
I'm trying to create (3) threads using pthread_create(), and print the thread number and ID in order, for (5) iterations.
Forgive my code, I'm fairly new to C, but I am seeing a strange pattern when my thread creations are printed. For example, my desired output is:
Iteration: 1 of 5
Thread 1 (ID: 140671542023744)
Thread 2 (ID: 140671533631040)
Thread 3 (ID: 140671525238336)
Iteration: 2 of 5
Thread 1 (ID: 140671542023744)
Thread 2 (ID: 140671533631040)
Thread 3 (ID: 140671525238336)
Iteration: 3 of 5
Thread 1 (ID: 140671542023744)
Thread 2 (ID: 140671533631040)
Thread 3 (ID: 140671525238336)
Iteration: 4 of 5
Thread 1 (ID: 140671542023744)
Thread 2 (ID: 140671533631040)
Thread 3 (ID: 140671525238336)
Iteration: 5 of 5
Thread 1 (ID: 140671542023744)
Thread 2 (ID: 140671533631040)
Thread 3 (ID: 140671525238336)
My actual output is:
Iteration: 1 of 5
Thread 1 (ID: 140671542023744)
Thread 2 (ID: 140671533631040)
Thread 3 (ID: 140671525238336)
Iteration: 2 of 5
Thread 1 (ID: 140671525238336) <-- Order starts reversing here for some reason
Thread 2 (ID: 140671533631040)
Thread 3 (ID: 140671542023744)
Iteration: 3 of 5
Thread 1 (ID: 140671542023744)
Thread 2 (ID: 140671533631040)
Thread 3 (ID: 140671525238336)
Iteration: 4 of 5
Thread 1 (ID: 140671525238336)
Thread 2 (ID: 140671533631040)
Thread 3 (ID: 140671542023744)
Iteration: 5 of 5
Thread 1 (ID: 140671542023744)
Thread 2 (ID: 140671533631040)
Thread 3 (ID: 140671525238336)
And advice would be greatly appreciated. It's driving me insane. My code is posted below:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
pthread_t threads[3];
pthread_mutex_t mutex;
void * printThread(void * arg) {
pthread_t id = pthread_self(); // Get pthread ID
printf("\t\tThread %d (ID: %ld)\n", arg + 1, id); // Print thread creation and ID, account for zero index
return NULL;
}
int main(void) {
int i, j;
int error;
if (pthread_mutex_init( & mutex, NULL) != 0) {
printf("\n Error: pthread_mutex_init failure. [%s]\n", strerror(error));
return 1;
} // Catch and print pthread_mutex_init error
printf("Begin multithreading...\n");
/* Create and print (3) threads by ID, for (5) iterations */
for (i = 0; i < 5; i++) {
printf("\t\nIteration: %d of 5\n\n", i + 1);
for (j = 0; j < 3; j++) {
error = pthread_create( & (threads[j]), NULL, & printThread, (void * ) j); // Create new thread
if (error != 0)
printf("\nError: pthread_create failure. [%s]\n", strerror(error));
sleep(2);
} // Catch and print pthread_create error
/* Syncrhonize threads */
pthread_join(threads[0], NULL);
pthread_join(threads[1], NULL);
pthread_join(threads[2], NULL);
}
printf("\nMultithreading complete.\n");
/* Cleanup threads and mutex */
pthread_exit( & threads);
pthread_mutex_destroy( & mutex);
return 0;
}
Solution 1:[1]
pthreads is meant to be a very opaque and generic API, so that application code using the pthreads API can be easily ported to as many (often wildly different) platforms as possible.
As part of that philosophy of opacity, the only limitation that pthreads places on the ID values returned by pthread_create() is that the ID of each valid (i.e. not-yet-joined) thread be unique with respect to all other valid threads in the process. Beyond that, all behaviors are left up to the platform's pthreads implementation to handle however it sees fit.
Given that, I don't believe there is any error in the posted code. The only error is the assumption that the IDs returned by pthread_create() should or will follow some additional rules beyond thread-ID-uniqueness -- that is not a valid assumption.
Solution 2:[2]
Answered my own question. I was able to circumnavigate the incorrect ordering of my thread creations by printing them from the thread array, as opposed to from a function within my pthread creation.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int thread;
pthread_t threads[3]; // Initialize thread array
pthread_mutex_t mutex;
void * printThread() {
pthread_mutex_lock( & mutex); // Lock code
pthread_t tid = pthread_self(); // Get thread
printf("\nThread %d (thread-id: %ld) created successfully.", thread + 1,
tid); // Print thread creation, account for zero index
pthread_mutex_unlock( & mutex); // Unlock code
return NULL;
}
int main(void) {
int iteration;
int error;
if (pthread_mutex_init( & mutex, NULL) != 0) {
printf("\n Error: pthread_mutex_init failure. [%s]\n", strerror(error));
return 1;
} // Catch and print pthread_mutex_init error
printf("Begin multithreading...\n");
/* Create and print three (3) threads by thread-id */
for (thread = 0; thread < 3; thread++) {
error = pthread_create( & (threads[thread]), NULL, & printThread, NULL); // Create new thread
sleep(1); // Necessary to ensure proper order
if (error != 0)
printf("\nError: pthread_create failure. [%s]\n", strerror(error));
} // Catch and print pthread_create error
/* Synchronize threads */
pthread_join(threads[0], NULL);
pthread_join(threads[1], NULL);
pthread_join(threads[2], NULL);
/* Print three (3) threads, in turn, for five (5) iterations */
for (iteration = 0; iteration < 5; iteration++) {
printf("\n\n\tIteration: %d of 5 - \n", iteration + 1); // Account for zero index
for (thread = 0; thread < 3; thread++) {
printf("\n\t\tThread %d (thread-id: %ld)", thread + 1,
threads[thread]); // Print threads in turn, account for zero index
sleep(1); // Sleep to simulate thread step
}
}
printf("\n\nMultithreading complete.\n");
/* Cleanup mutex and threads */
pthread_mutex_destroy( & mutex);
pthread_exit( & threads);
return 0;
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Jeremy Friesner |
| Solution 2 |
