Этот код передает один и тот же адрес k
каждому потоку, но изменяет значение в этой памяти :
for(i=0;i<10;i++){
(*k)=i;
printf("k: %d\n",(*k));
pthread_create(&(threads_array[i]),NULL,calculate,(void*)k);
}
К тому времени, когда этот код запускается
void *calculate(void *i){
sem_wait(&s);
int j=(*((int*)i));
.
.
.
значение, вероятно, изменилось, потому что основной поток изменил его.
Это было бы лучше, так как оно передает значение из i
, но это зависит от существования intptr_t
и поведения платформы, позволяющего преобразовать обратно в int
, поэтому не строго соответствует C-коду:
for(i=0;i<10;i++){
pthread_create(&(threads_array[i]),NULL,calculate,(void*)(intptr_t)i);
}
и
void *calculate(void *i){
sem_wait(&s);
int j= (intptr_t)i;
Это передает значение из i
как значение указателя void *
.
Но если intptr_t
существует, то лучше:
intptr_t i;
.
.
.
for(i=0;i<10;i++){
pthread_create(&(threads_array[i]),NULL,calculate,(void*)i);
}
и
void *calculate(void *i){
sem_wait(&s);
intptr_t j= (intptr_t)i;
Реально, уже не так много платформ, на которых этот подход работать не будет.
В качестве альтернативы, в строго соответствующем C, чтобы передать адрес фактического значения int
, вам нужен отдельный int
для каждого потока, который гарантированно существует во время работы потока:
// this is a local variable, but since it's in the same scope as
// both pthread_create() and pthread_join(), it will still exist
// for the entire lifetime of each thread created
int threadnum[10];
for(i=0;i<10;i++){
threadnum[i]=i;
pthread_create(&(threads_array[i]),NULL,calculate,(void*)&(threadnum[i]));
}
и
void *calculate(void *i){
sem_wait(&s);
int j=(*((int*)i));