Как использовать общие переменных в многопоточных программах с++?

Всем привет.

Хотел проверить как работает многопоточность в с++, но с кодом ниже я всегда получаю "safe_mode: FALSE"

Идея того, что я хочу сделать это снимать показания сенсоров с больший скоростью (while loop) в нескольких параллельных процессах, но записывать их в общие переменные , которую читает главная функция (тоже while loop) и в зависимости от значений общих переменных ведет себя по разному. Как это лучше всего реализовать?

#include <thread>
#include <iostream>

using namespace std;

bool safe_mode = true;

bool *pnt_safe_mode = &safe_mode;

void stupidFunc() {
	int i = 0;

	while (i <= 10000)
	{
		if (*pnt_safe_mode == true)
		{
			*pnt_safe_mode = false;
		}
		else {
			*pnt_safe_mode = true;
		}
		i++;
	}
}


int main()
{
	std::thread t(stupidFunc);
	t.detach();

	for (int i = 0; i <= 10000; i++) {
		if (*pnt_safe_mode) {
			cout << "safe_mode: TRUE\n";
		}
		else {
			cout << "safe_mode: FALSE\n";
		}
	}

	system("pause");
	return 0;
}
  • Вопрос задан
  • 788 просмотров
Решения вопроса 1
Для простых типов данных можно использлвать std::atomic
Например для вашей программы
std::atomic<bool> safe_mode = true;

void stupidFunc() {
  int i = 0;

  while (i <= 10000)
  {
    if (safe_mode == true)
    {
      safe_mode = false;
    }
    else {
      safe_mode = true;
    }
    i++;
  }
}

int main()
{
  std::thread t(stupidFunc);
  t.detach();

  for (int i = 0; i <= 10000; i++) {
    if (safe_mode) {
      cout << "safe_mode: TRUE\n";
    }
    else {
      cout << "safe_mode: FALSE\n";
    }
  }

  system("pause");
  return 0;
}
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
Olej
@Olej
инженер, программист, преподаватель
как работает многопоточность в с++

в нескольких параллельных процессах

Вы уж как-то определитесь кто вас интересует: потоки или процессы.

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

Пытаться засинхронизироваться на простых переменных (как у вас safe_mode ... и любые изыски вокруг) - бессмысленно.
Ответ написан
Nipheris
@Nipheris Куратор тега C++
Ну начнем с того, что 10000 итераций на современном процессоре выполнится настолько быстро, что вероятно уложится в отведенный потоку квант времени, и второй поток скорее всего даже не успеет получить процессорное время, чтобы поменять вашу переменную. Поэтому ИСКЛЮЧИТЕЛЬНО в целях эксперимента можете попробовать увеличить число итераций хотя бы до 10 миллионов, и отключить по максимуму оптимизации (не по причине скорости, а по причине потенциального выбрасывания кода компилятором), т.к. наверняка количество итераций есть причина неудачи в вашем эксперименте.

А если по-серьезному, вам уже дали советы как поступать - без нормальной синхронизации в многопоточной среде у вас никакие общие переменные результатов дать не могут. Если уж очень не хочется брать мьютекс (хотя чтобы его не брать, нужно четко знать что он не подходит), можете превратить вашу общий флажок в спинлок, но кодом на плюсах тут не отделаешься.

С архитектурной точки зрения, если у вас снятие показаний, то у вас просто классический случай producer-consumer - впилите потокобезопасную очередь, и пользуйтесь.
Ответ написан
@iv_k
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы