Общий доступ к данным в pthreads

Мои вопросы: сколько значений может принимать вывод следующего кода? Каковы эти ценности? В чем причина разных ценностей? Как мы можем предотвратить появление разных значений?

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<unistd.h>

int shared_data = 100;


void* thread_function(void *args)
{
    long temp;
    long *j = (long *) args;
    temp = shared_data;
    temp = temp + &j;
    shared_data = temp;
    
    return (NULL);
}



int main() 
{

long i = 0;
long tinfo[] = {1,2,3};
pthread_t ids[3];

for(int i=0 ;i<3;i++)
{
    pthread_create(ids+i,NULL,&thread_function, &tinfo[i]);
}

for(int i=0 ;i<3;i++)
{
    pthread_join(ids[i],NULL);
}

printf("shared data = %d\n",shared_data);

}

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

Все потоки изменяют общие данные без каких-либо средств управления для предотвращения одновременного доступа. Поведение полностью неопределенно, и нет никаких полезных прогнозов, которые можно сделать.

Jonathan Leffler 02.06.2024 05:59
long *j = (long *) args; -- в сторону: вам не нужно приводить указатели void в C.
ad absurdum 02.06.2024 06:01

«Как мы можем предотвратить появление разных ценностей?» - Чтобы получить определенное поведение, синхронизируйте потоки.

Ted Lyngmo 02.06.2024 06:23

Вычисление temp = temp + &j; сомнительно — вы добавляете к вычислению адрес локальной переменной-указателя. Вероятно, вам следует использовать temp += *j;, чтобы добавить значение, на которое указывает указатель. Ваш компилятор должен кричать о добавлении — и вы должны обращать внимание на вопли вашего компилятора! Переменная long i = 0; не используется.

Jonathan Leffler 02.06.2024 06:34

Вероятно, вам понадобится использовать pthread_mutex_t (мьютекс — взаимное исключение) для управления доступом к shared_data (см. pthread_mutex_init() и так далее). По крайней мере, это самый простой способ справиться с проблемами одновременного доступа. Это не ускорит процесс, но сделает его более надежным. Последовательность по-прежнему отсутствует — то, что происходит, зависит от своеобразного поведения планирования потоков на вашей конкретной машине — но неопределенного поведения будет меньше.

Jonathan Leffler 02.06.2024 06:39

Первым делом скомпилируйте код с помощью -Wall -Werror.

n. m. could be an AI 02.06.2024 07:09

В идеале заголовок вашего вопроса должен представлять собой краткое изложение вопроса или ссылаться на его тему. Например, лучшим названием могло бы быть «Общий доступ к данным в pthreads». На самом деле это не пример «системного программирования» — это проблема многопоточности в целом.

Clifford 02.06.2024 10:38
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
7
98
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Предполагая, что ожидается ответ, а не исправление многих ошибок, которые, вероятно, являются непреднамеренными, при ответе на этот вопрос вам следует сформулировать некоторые предположения, чтобы справиться с «неопределенным» поведением плохо сформированного кода. Это продемонстрирует ваше знание таких вопросов, если вопрос действительно будет об этом, но это также позволит вам ответить на вопрос так, как, вероятно, предполагало учреждение. Они, возможно, даже исправят вопрос для следующего кандидата! К сожалению, мир полон таких некорректных вопросов на собеседовании — если вы хотите поступить на курс, вам нужно сыграть в игру. Но вы можете не захотеть записываться, если это, возможно, свидетельствует о качестве их преподавания.

Во всяком случае, если мы заявим:

Предположения:

  • Код выполняется на одном ядре по одному активному потоку за раз.
  • Каждый запущенный поток будет выполняться до завершения, не будучи вытеснен каким-либо другим потоком без синхронизации или взаимного исключения.
  • Любой доступ к shared_data будет явным, несмотря на отсутствие квалификатора volatile.

Тогда изменчивость вывода будет зависеть от порядка запуска каждого потока, который не обязательно должен совпадать с порядком их создания. Таким образом, речь идет о перестановках 1,2,3, что равно 3 x 2 x 1 = 6. Таким образом, ответ заключается в выполнении вычисления функции потока для каждой из шести возможных перестановок порядка выполнения.

Без допущений результат совершенно не определен.

Учитывая эти предположения, «исправление» состоит в том, чтобы вообще не использовать потоки, а вызывать функцию последовательно в одном фиксированном порядке. Несомненно, существуют более сложные решения, использующие синхронизацию потоков, но нет никакой практической пользы от выполнения потоков до завершения в определенном последовательном порядке.

Другие вопросы по теме