The book says that we need to eliminate global or static data to be thread safe. I think that thread safe means that there is no race condition in the program.
However, in the following example, it changes the local veritable "Point pt_ptr" from a non-pointer type to a pointer type"Point *pt_ptr" in order to prevent the race condition. I noticed that he uses "malloc", which means he is going to create something in the heap. And things in the heap are shared by all the threads... Since it creates something that is shared, it prevents the data race BUT will it be thread UNSAFE?
int main(void) {
pthread_t tids[NUM_THREADS];
int i;
Point *pt_ptr;
for (i= 0; i < NUM_THREADS; i++) {
pt_ptr= malloc(sizeof(*pt_ptr));
pt_ptr->x= i;
pt_ptr->y= 3 * i + 2;
pthread_create(&tids[i], NULL, print_point, pt_ptr);
}
It will only be thread unsafe if more than one thread attempts to access the same memory space (variable as an example) without some thread-safety mechanism, such as mutex or semaphore. They are used to provide a blocking mechanism, so that one thread will sit and "wait" until the current owning thread is thru, at which point the 2nd thread will have the ability to access/modify the variable.
Think of them as numbers at the DMV, and you have to wait until yours is called before you can get service.
In this case, each iteration of the loop calls malloc(), creating a new block of memory that is passed only to one thread. (As J. Murray correctly pointed out.) These dynamic variables are not really global at all. You could instead write:
int main(void)
{
pthread_t tids[NUM_THREADS];
for ( int i = 0; i < NUM_THREADS; i++) {
Point * const pt_ptr = malloc(sizeof(*pt_ptr));
assert(pt_ptr); /* TODO: Handle the out-of-memory error. */
pt_ptr->x= i;
pt_ptr->y= 3 * i + 2;
pthread_create(&tids[i], NULL, print_point, pt_ptr);
}
/* ... */
return EXIT_SUCCESS;
}
That version makes clearer that each iteration of pt_ptr is really a separate local variable.
Related
poll() in main() waits for some sort of a trigger from another application and when there is a trigger, pollHandler() is executed. In pollHandler(), I want to start 'n' number of threads based on the number of requests in the poll message.
But now in pollHandler(), when I want to use pthread_join in a different for loop, I don't have access to the thread_ids. I could create an array of pthread ids and use it outside the for loop block accessible to both pthread_create and pthread_join but the poll() function is active and it could get called again and again, thus overwriting the thread ids. How do I keep things clean here - wait for each thread to finish and make room to have more threads?
int pollHandler(){
int num_req = poll.size();
for(int i=0; i < num_req; i++){
// start thread for each req
pthread_t tid;
// thread paramters dynamically allocated and freed later
struct parameters *p = (struct parameters*)malloc(sizeof(struct parameters));
if((pthread_create(&tid, NULL, thread_func, p) != 0){
return -1;
}
}
for(int i=0; i < num_req; i++){
// pthread_join here but no access to thread ids?
}
return 0;
}
int main(){
......
while(1){
poll(); //waits for a trigger from another application
}
}
I want to start 'n' number of threads based on the number of requests in the poll message.
This design is fundamentally flawed: if you get a request with (say) 10,000 requests, it is unlikely that you will be able to create a separate thread to handle each one, and even if you could, thread creation and destruction are inefficient and best avoided.
A much better design is to start a thread pool, and dispatch work to them, waiting for all work to be completed before returning, as Martin James suggested.
That said, here is correct (except error checking is omitted for clarity) way to implement your current design:
int pollHandler(){
int num_req = poll.size();
pthread_t *tids = calloc(num_req * sizeof(pthread_t));
for(int i=0; i < num_req; i++){
// start thread for each req
// thread paramters dynamically allocated and freed later
struct parameters *p = (struct parameters*)malloc(sizeof(struct parameters));
if((pthread_create(&tid[i], NULL, thread_func, p) != 0){
// bug here.
return -1;
}
}
for(int i=0; i < num_req; i++){
pthread_join(tids[i], NULL);
}
free(tids);
return 0;
I could create an array of pthread ids and use it outside the for loop block accessible to both pthread_create and pthread_join but the poll() function is active and it could get called again and again, thus overwriting the thread ids.
Unless pollHandler() can interrupt another pollHandler(), it will not be invoked until previous invocation finishes, so the code above is "safe".
If pollHandler() can run as part of an interrupt, then your code is already hopelessly broken (neither malloc, nor pthread_create are async-signal safe and thus can't be called in signal handler).
P.S. What's up with //bug here?
You can't just return there -- you need to join the threads you've already created. You would also need to free(tids); there as well.
Consider the following section of a C function:
for (int i = 0; i < n; ++i) {
thread_arg *arg = (thread_arg *) malloc(sizeof(thread_arg));
arg->random_value = random_value;
arg->message = &(message[i * 10]);
if (pthread_create(NULL, NULL, thread_start, (void *) &arg)) {
perror("pthread_create");
exit(EXIT_FAILURE);
}
}
In this for loop, I create n threads which all perform a common routine with different parameters. This for loop is part of a bigger function which returns a data structure which gets modified by all threads in parallel. Thus, it is important that this bigger function won't return before all threads are done.
I was hoping to find a simpler way then giving an individual ID to all these threads and joining afterwards with pthread_join.Is there any general approach to say to a function something like "hey, don't return until all threads you've created returned"?
There are at least two other ways:
Use pthread barriers. The name barrier is used in a completely different sense than you usually hear it when talking about concurrency. Here, it's a synchronization primitive that lets each of a set of threads (waiters on it) block until all of them have reached it, then unblocks them all together. You'd first initialize the barrier in some shared location with n+1 as the count, then have both the function itself and all the n threads it created call pthread_barrier_wait before finishing. Assuming you do it this way, after returning from the wait, the n threads can no longer access the shared state; they need to immediately return.
Create the same thing (or a simplified version of it) with a condvar and mutex. Have a count, protected by a mutex, of how many of the n threads are still working. The function that created them can then do:
pthread_mutex_lock(&cnt_mtx);
while (count > 0) pthread_cond_wait(&cnt_cv, &cnt_mtx);
pthread_mutex_unlock(&cnt_mtx);
Generally, though, I'd use pthread_join here. That's what it's for.
This question already has an answer here:
Pthread_create() incorrect start routine parameter passing
(1 answer)
Closed 3 years ago.
I tried to build a program which should create threads and assign a Print function to each one of them, while the main process should use printf function directly.
Firstly, I made it without any synchronization means and expected to get a randomized output.
Later I tried to add a mutex to the Print function which was assigned to the threads and expected to get a chronological output but it seems like the mutex had no effect about the output.
Should I use a mutex on the printf function in the main process as well?
Thanks in advance
My code:
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
pthread_t threadID[20];
pthread_mutex_t lock;
void* Print(void* _num);
int main(void)
{
int num = 20, indx = 0, k = 0;
if (pthread_mutex_init(&lock, NULL))
{
perror("err pthread_mutex_init\n");
return errno;
}
for (; indx < num; ++indx)
{
if (pthread_create(&threadID[indx], NULL, Print, &indx))
{
perror("err pthread_create\n");
return errno;
}
}
for (; k < num; ++k)
{
printf("%d from main\n", k);
}
indx = 0;
for (; indx < num; ++indx)
{
if (pthread_join(threadID[indx], NULL))
{
perror("err pthread_join\n");
return errno;
}
}
pthread_mutex_destroy(&lock);
return 0;
}
void* Print(void* _indx)
{
pthread_mutex_lock(&lock);
printf("%d from thread\n", *(int*)_indx);
pthread_mutex_unlock(&lock);
return NULL;
}
All questions of program bugs notwithstanding, pthreads mutexes provide only mutual exclusion, not any guarantee of scheduling order. This is typical of mutex implementations. Similarly, pthread_create() only creates and starts threads; it does not make any guarantee about scheduling order, such as would justify an assumption that the threads reach the pthread_mutex_lock() call in the same order that they were created.
Overall, if you want to order thread activities based on some characteristic of the threads, then you have to manage that yourself. You need to maintain a sense of which thread's turn it is, and provide a mechanism sufficient to make a thread notice when it's turn arrives. In some circumstances, with some care, you can do this by using semaphores instead of mutexes. The more general solution, however, is to use a condition variable together with your mutex, and some shared variable that serves as to indicate who's turn it currently is.
The code passes the address of the same local variable to all threads. Meanwhile, this variable gets updated by the main thread.
Instead pass it by value cast to void*.
Fix:
pthread_create(&threadID[indx], NULL, Print, (void*)indx)
// ...
printf("%d from thread\n", (int)_indx);
Now, since there is no data shared between the threads, you can remove that mutex.
All the threads created in the for loop have different value of indx. Because of the operating system scheduler, you can never be sure which thread will run. Therefore, the values printed are in random order depending on the randomness of the scheduler. The second for-loop running in the parent thread will run immediately after creating the child threads. Again, the scheduler decides the order of what thread should run next.
Every OS should have an interrupt (at least the major operating systems have). When running the for-loop in the parent thread, an interrupt might happen and leaves the scheduler to make a decision of which thread to run. Therefore, the numbers being printed in the parent for-loop are printed randomly, because all threads run "concurrently".
Joining a thread means waiting for a thread. If you want to make sure you print all numbers in the parent for loop in chronological order, without letting child thread interrupt it, then relocate the for-loop section to be after the thread joining.
I'm creating a multi-thread program in C and I've some troubles.
There you have the function which create the threads :
void create_thread(t_game_data *game_data)
{
size_t i;
t_args *args = malloc(sizeof(t_args));
i = 0;
args->game = game_data;
while (i < 10)
{
args->initialized = 0;
args->id = i;
printf("%zu CREATION\n", i);//TODO: Debug
pthread_create(&game_data->object[i]->thread_id, NULL, &do_action, args);
i++;
while (args->initialized == 0)
continue;
}
}
Here you have my args struct :
typedef struct s_args
{
t_game_data *object;
size_t id;
int initialized;
}args;
And finally, the function which handle the created threads
void *do_action(void *v_args)
{
t_args *args;
t_game_data *game;
size_t id;
args = v_args;
game = args->game;
id = args->id;
args->initialized = 1;
[...]
return (NULL);
}
The problem is :
The main thread will create new thread faster than the new thread can init his variables :
args = v_args;
game = args->game;
id = args->id;
So, sometime, 2 different threads will get same id from args->id.
To solve that, I use an variable initialized as a bool so make "sleep" the main thread during the new thread's initialization.
But I think that is really sinful.
Maybe there is a way to do that with a mutex? But I heard it wasn't "legal" to unlock a mutex which does not belong his thread.
Thanks for your answers!
The easiest solution to this problem would be to pass a different t_args object to each new thread. To do that, move the allocation inside the loop, and make each thread responsible for freeing its own argument struct:
void create_thread(t_game_data *game_data) {
for (size_t i = 0; i < 10; i++) {
t_args *args = malloc(sizeof(t_args));
if (!args) {
/* ... handle allocation error ... */
} else {
args->game = game_data;
args->id = i;
printf("%zu CREATION\n", i);//TODO: Debug
if (pthread_create(&game_data->object[i]->thread_id, NULL,
&do_action, args) != 0) {
// thread creation failed
free(args);
// ...
}
}
}
}
// ...
void *do_action(void *v_args) {
t_args *args = v_args;
t_game_data *game = args->game;
size_t id = args->id;
free(v_args);
args = v_args = NULL;
// ...
return (NULL);
}
But you also write:
To solve that, I use an variable initialized as a bool so make "sleep"
the main thread during the new thread's initialization.
But I think that is really sinful. Maybe there is a way to do that
with a mutex? But I heard it wasn't "legal" to unlock a mutex which
does not belong his thread.
If you nevertheless wanted one thread to wait for another thread to modify some data, as your original strategy requires, then you must employ either atomic data or some kind of synchronization object. Your code otherwise contains a data race, and therefore has undefined behavior. In practice, you cannot assume in your original code that the main thread will ever see the new thread's write to args->initialized. "Sinful" is an unusual way to describe that, but maybe appropriate if you belong to the Church of the Holy C.
You could solve that problem with a mutex by protecting just the test of args->initialized in your loop -- not the whole loop -- with a mutex, and protecting the threads' write to that object with the same mutex, but that's nasty and ugly. It would be far better to wait for the new thread to increment a semaphore (not a busy wait, and the initialized variable is replaced by the semaphore), or to set up and wait on a condition variable (again not a busy wait, but the initialized variable or an equivalent is still needed).
The problem is that in create_thread you are passing the same t_args structure to each thread. In reality, you probably want to create your own t_args structure for each thread.
What's happening is your 1st thread is starting up with the args passed to it. Before that thread can run do_action the loop is modifying the args structure. Since thread2 and thread1 will both be pointing to the same args structure, when they run do_action they will have the same id.
Oh, and don't forget to not leak your memory
Your solution should work in theory except for a couple of major problems.
The main thread will sit spinning in the while loop that checks the flag using CPU cycles (this is the least bad problem and can be OK if you know it won't have to wait long)
Compiler optimisers can get trigger happy with respect to empty loops. They are also often unaware that a variable may get modified by other threads and can make bad decisions on that basis.
On multi core systems, the main thread may never see the change to args->initiialzed or at least not until much later if the change is in the cache of another core that hasn't been flushed back to main memory yet.
You can use John Bollinger's solution that mallocs a new set of args for each thread and it is fine. The only down side is a malloc/free pair for each thread creation. The alternative is to use "proper" synchronisation functions like Santosh suggests. I would probably consider this except I would use a semaphore as being a bit simpler than a condition variable.
A semaphore is an atomic counter with two operations: wait and signal. The wait operation decrements the semaphore if its value is greater than zero, otherwise it puts the thread into a wait state. The signal operation increments the semaphore, unless there are threads waiting on it. If there are, it wakes one of the threads up.
The solution is therefore to create a semaphore with an initial value of 0, start the thread and wait on the semaphore. The thread then signals the semaphore when it is finished with the initialisation.
#include <semaphore.h>
// other stuff
sem_t semaphore;
void create_thread(t_game_data *game_data)
{
size_t i;
t_args args;
i = 0;
if (sem_init(&semaphore, 0, 0) == -1) // third arg is initial value
{
// error
}
args.game = game_data;
while (i < 10)
{
args.id = i;
printf("%zu CREATION\n", i);//TODO: Debug
pthread_create(&game_data->object[i]->thread_id, NULL, &do_action, args);
sem_wait(&semaphore);
i++;
}
sem_destroy(&semaphore);
}
void *do_action(void *v_args) {
t_args *args = v_args;
t_game_data *game = args->game;
size_t id = args->id;
sem_post(&semaphore);
// Rest of the thread work
return NULL;
}
Because of the synchronisation, I can reuse the args struct safely, in fact, I don't even need to malloc it - it's small so I declare it local to the function.
Having said all that, I still think John Bollinger's solution is better for this use-case but it's useful to be aware of semaphores generally.
You should consider using condition variable for this. You can find an example here http://maxim.int.ru/bookshelf/PthreadsProgram/htm/r_28.html.
Basically wait in the main thread and signal in your other threads.
i'm working on gcc ,
i'm wondering if this is possible:
I have a function (NOTmain but aLocalFn) and I declare a local variable in it. Then I pass this local argument as a thread argument. is it doable? or there is the chance (depending on what is run first) that the aLocalVar will be lost before threadFunction is run and the reference idxPtr will be pointing to senselessness??
int *threadFunction(void *idxPtr){
int rec_idx=(int) *idxPtr;
//work in the thread with this variabel rec_idx
}
int aLocalFn(){
int aLocalVar=returnsRecordIndex();
pthread_create(&thread_id,&attr_detached,threadFunction, &aLocalVar)!=0)
return 0;
}
thank you for your help
This code is incorrect. The function aLocalFn may return before the thread function starts executing. And so by the time the thread function reads the local variable, the scope of that variable may have ended.
What can confuse matters is that this code may very well appear to work, at least some of the time. However, it is incorrect and you should use heap allocated memory instead.
your code has a life-time issue with "aLocalVar"
if you just want to pass an integer, here is a non-portable way to do it.
it does not work on some platforms, but you are not likely to encounter those.
void threadFunction ( void * idxptr ) {
int rec_idx = (int) idxptr;
....
}
int rec_idx = returnsRecordIndex();
pthread_create (&thread1, &attr_detached, (void *) &threadFunction, (void *)rec_idx);
It's doable, but it's not done in the code in your question. You will have to add a signal variable to indicate when the new thread is done using the variable. Then your outer function can return.
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t signal = PTHREAD_COND_INITIALIZER;
int done;
int *threadFunction(void *idxPtr){
int rec_idx=(int) *idxPtr;
pthread_mutex_lock(&lock);
done = 1;
pthread_cond_signal(&signal);
pthread_mutex_unlock(&lock);
//work in the thread with this variabel rec_idx
}
int aLocalFn(){
int aLocalVar=returnsRecordIndex();
done = 0;
pthread_create(&thread_id,&attr_detached,threadFunction, &aLocalVar)!=0)
pthread_mutex_lock(&lock);
while (!done)
pthread_cond_wait(&signal, &lock);
pthread_mutex_unlock(&lock);
return 0;
}
Note that this example code is itself not thread safe (if multiple threads call aLocalFn).
This does complicate the code, and locking is expensive. So in most cases you're probably better off storing the data in the heap and letting the new thread or pthread_join code free it.
#pizza's answer is what I'd do. Another way for you to do it would be to use malloc/free as #David hinted at. I would certainly do this over the wait loop proposed in other answers here.
int *threadFunction(void *idxPtr){
int rec_idx = *(int *)idxPtr;
// free up our int buffer
free(idxPtr);
...
}
int aLocalFn(){
int aLocalVar = returnsRecordIndex();
// allocate some space for our int
int *intBuf = (int *)malloc(sizeof(int));
*intBuf = aLocalVar;
pthread_create(&thread_id,&attr_detached,threadFunction, intBuf)!=0)
return 0;
}
Whenever you are passing variables to a thread function, it is your job to ensure that the variable remains alive and valid till the thread function is done using it.
In your case aLocalFn() continues to execute simultaneously with the new thread and may even finish execution before the thread, that leaves you with an dangling pointer(pointer pointing to data that may not exist) in thread function since the local variable aLocalVar in the function ceases to exist after function returns.