pthread_create время обратной записи - PullRequest
0 голосов
/ 14 июня 2011

В вызове pthread_create (& id, NULL, & start_routine, arg) гарантируется ли запись идентификатора потока в id до запуска start_routine?Справочные страницы ясны, что start_routine может, но не обязательно начнет выполняться до того, как будет возвращен вызов pthread_create, но они молчат, когда идентификатор потока записывается обратно в переданный аргумент потока.У меня есть обертка вокруг pthread_create:

int mk_thread(pthread_t *id) {
  pthread_t tid;
  pthread_create(&tid,NULL,ThreadStart,NULL);
  if (id == NULL) {
    pthread_detach(tid);
  } else {
    *id=lid;
  }
}

, которая, очевидно, может запустить процедуру запуска перед обратной записью.Я изменил его на

int mk_thread(pthread_t *id) {
  pthread_t tid,tidPtr=id?id:&tid;
  pthread_create(tidPtr,NULL,ThreadStart,NULL);
  if (id == NULL) {
     pthread_detach(tid);
  }
}

Это переписывание гораздо более стабильно на практике, но на самом деле это исправление или просто меньшее окно для состояния гонки?

Ответы [ 2 ]

2 голосов
/ 14 июня 2011

Идентификатор потока определенно записывается до того, как pthread_create вернется.Если вы подумаете об этом, pthread_create не сможет работать другим способом.Он не может делегировать запись идентификатора потока в новый поток, поскольку к моменту запуска нового потока переменная pthread_t может находиться вне области действия.

Соответствующий текст:

После успешного завершения pthread_create () должен сохранить идентификатор созданного потока в расположении, указанном потоком.

http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_create.html) Обратите внимание, что в нем говорится «об успешном завершении»функции, а не «в неопределенное время после успешного завершения».

Более интересный вопрос, и мне неясно по этому вопросу, должно ли pthread_create завершить запись идентификатора потока в место назначениядо начала функции запуска нового потока, т. е. может ли новый поток сразу увидеть свой собственный идентификатор потока, например, если он будет сохранен в глобальной переменной. Я подозреваю, что ответ - нет.

Редактировать: Перечитывая ваш вопрос, кажется, что вы, возможно, действительно задавали вопрос об этом последнем, более интересном вопросе.n для функции запуска нового потока, чтобы использовать идентификатор потока, записанный pthread_create.Ваш новый поток может (и должен) просто использовать pthread_self, чтобы получить свой собственный идентификатор потока.

0 голосов
/ 15 января 2013

Я полагаю, что ничто в спецификации не требует, чтобы pthread_create присвоил свой выходной параметр pthread_t *thread до того, как код в start_routine начнет выполняться.

Из практических соображений следующая программа успешно выполняется во многих реализациях pthreads(freebsd8 i386 и debian gnu / linux amd64), но не может найти интересующий меня (debian / kfreebsd9 amd64):

#include <pthread.h>
#include <assert.h>
#include <stdint.h>
#include <stdio.h>

pthread_t th;

void *asserter(void* unused) {
        pthread_t self = pthread_self(), th_=th;
        printf("th=%jd self=%jd\n", (intmax_t)th_, (intmax_t)self);
        assert(pthread_equal(th_, self));
}

int main() {
        int i;
        for(i=0; i<1000; i++) {
                pthread_create(&th, NULL, asserter, NULL);
                pthread_join(th, NULL);
        }
        return 0;
}

, который сказал, я не уверен, что понимаю, как эта деталь поведения имеет отношениек двум вариантам кода, которые вы предлагаете в оригинальном вопросе.Хотя мне приходит в голову, что если pthread_create записывает другие значения в *thread во время его выполнения, и вы используете значение *id в другом потоке, это может быть актуально.Стандарт не устанавливает, что никакие другие «промежуточные» значения не записываются в *thread во время успешного выполнения pthread_create.

...