pthreads - ранее созданный поток использует новое значение (обновляется после создания потока) - PullRequest
0 голосов
/ 21 сентября 2010

Так вот мой сценарий.Во-первых, у меня есть структура -

struct interval
{
    double lower; 
    double higher;
}

Теперь моя функция потока -

void* thread_function(void* i)
{
    interval* in = (interval*)i; 
    double a = in->lower; 
    cout << a; 
    pthread_exit(NULL)
}

В основном, скажем, я создаю эти 2 темы -

pthread_t one,two; 
interval i; 

i.lower = 0; i.higher = 5; 
pthread_create(&one,NULL,thread_function,&i);

i.lower=10; i.higher = 20; 
pthread_create(&two,NULL,thread_function, &i); 

pthread_join(one,NULL);
pthread_join(two,NULL);

Здесь проблема.В идеале нить "one" должна распечатать 0, а нить "two" должна распечатать 10. Однако этого не происходит.Иногда я получаю две десятки.

Это так задумано?Другими словами, к моменту создания потока значение в i.lower уже изменилось в main, поэтому оба потока в итоге используют одно и то же значение?

Ответы [ 4 ]

3 голосов
/ 21 сентября 2010

Ваша заявка недетерминирована.
Пока неизвестно, когда будет запланирован запуск потока.

Примечание. Создание потока не означает, что он начнет выполняться немедленно (или даже первым). Второй созданный поток может начать работать раньше первого (все зависит от ОС и оборудования).

Чтобы получить детерминированное поведение, каждому потоку должны быть предоставлены его собственные данные (которые не изменены основным потоком).

pthread_t one,two; 
interval oneData,twoData 

oneData.lower = 0; oneData.higher = 5; 
pthread_create(&one,NULL,thread_function,&oneData);

twoData.lower=10; twoData.higher = 20; 
pthread_create(&two,NULL,thread_function, &twoData); 

pthread_join(one,NULL);
pthread_join(two,NULL);

Я бы не назвал это намеренно.
Я бы скорее назвал это побочным эффектом политики планирования. Но наблюдаемое поведение - это то, чего я ожидал.

3 голосов
/ 21 сентября 2010

Это задумано?

Да. Не указано, когда именно начнутся потоки и когда они получат доступ к этому значению. Вы должны дать каждому из них свою копию данных.

1 голос
/ 21 сентября 2010

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

Прямое решение вашей непосредственной проблемы состоит в том, чтобы хранить разные интервалы с разными данными и передавать отдельный поток каждому потоку, т.е.

interval i, j;
i.lower = 0; j.lower = 10;
pthread_create(&one,NULL,thread_function,&i);
pthread_create(&two,NULL,thread_function,&j);

Это, конечно, решит вашу непосредственную проблему. Но вскоре вы, вероятно, задаетесь вопросом, что делать, если вы хотите, чтобы несколько потоков фактически использовали одни и те же данные. Что если поток 1 хочет внести изменения в i, а поток 2 хочет принять это во внимание? Вряд ли было бы много смысла заниматься многопоточным программированием, если бы каждому потоку приходилось хранить свою память отдельно от других (ну, на данный момент, оставив сообщение вне картинки). Введите взаимные блокировки! Я подумал, что я хотел бы дать вам понять, что вы захотите рассмотреть эту тему раньше, чем позже, так как это также поможет вам понять основы потоков в целом и необходимые изменения в менталитете, которые сопровождают многопоточность программирования.

Кажется, я помню, что это является приличным коротким введением в pthreads, включая начало работы с пониманием блокировки и т. Д.

1 голос
/ 21 сентября 2010

Это классическое «состояние гонки»;где результаты варьируются в зависимости от того, какой поток выигрывает «гонку».У вас нет возможности узнать, какая нить будет «выигрывать» каждый раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...