You get to pass an integral value to the thread. You have to decide on both sides (passing in the arg and using it within the thread function) what you're going to pass.
If you want to pass you number as an integer, then you're reinterpreting the arg to be an int.
If you want to pass the address of the integer, then you're reinterpreting the arg to be an int*.
I guess your thread function is expecting the former and you were passing the latter. This is the sort of thing that can happen when you bypass the language's type system.
The race condition happens when you pass the address of the lots_of_threads variable, because it can happen that the new thread reads the data at this address after it was already incremented in the next iteration of the for loop at line 14.
In the second case, you pass the value of lots_of_threads to the function, i.e. a copy is made before the creation of the thread, thus no race condition.
Regarding your question about the cast to (void*):
When you cast, nothing happens. The cast just tells the compiler that the value of lots_of_threads is a pointer, i.e. an address, instead of an integer. But the compiled program won't try to access this address (if it did, it would very likely crash, since the value of lots_of_threads does not represent a valid address).
The reason why this cast is done, is because you want to pass an int to the new thread, but pthread_create() wants a void*. So to avoid a "type mismatch" compilation error, you cast your int to a void*, and cast it back to int in thread_function().
lloydchristmas759 is correct about the use of the parameter. The value threads see is indeterminate.
The reason why void* is used to pass the parameter is that you can pass anything one thing to a thread function. The idea is that you pack all your stuff into a record (struct), and pass the address of that. You're not constrained to passing just the address of an int, but the address of anything.
but what if I wanted to pass by value a datatype whose size is much larger than the sizeof void * as in the second part of the above code, will it still work?
but what if I wanted to pass by value a datatype whose size is much larger than the sizeof void * as in the second part of the above code, will it still work?
Nope. In this case you will have to pass a pointer and make sure there is no race condition. You can do it like that:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
struct big_struct {
size_t thread_id;
int a;
int b;
int c;
} my_struct;
...
for(my_struct.thread_id = 0; my_struct.thread_id< NUM_THREADS; my_struct.thread_id++) {
struct big_struct* copy = malloc(sizeof(*copy));
*copy = my_struct;
res = pthread_create(&(a_thread[lots_of_threads]), NULL, thread_function, (void *)copy);
}
Note that the new threads will be responsible for freeing the malloc()ated memory.
but how do I use/cast it in the thread function? when I tried to call 1 of the functions in the thread function, it gave me an error:
test.cpp:165: warning: pointer of type ‘void *’ used in arithmetic
test.cpp:165: error: ‘void*’ is not a pointer-to-object type
void * threadfunc(void *param)
{
if (FuncToPassPtr* flist = reinterpret_cast<FuncToPassPtr*>(param)
{
for (size_t i = 0; i < 3; ++i)
flist[i](i, i * i);
// ...
}
return 0;
}
I've not compiled it. I will say that I'd never do it like that myself. I'd pass the context in a struct at the very least, but would more likely pass the context in a thread class.
Does programs which use pthreads run faster and in parallel on
1) multicore processors
2) processors with hyperthreading technology
as opposed to programs which are not multithreaded?