Форум программистов, компьютерный форум CyberForum.ru

Нужно ли синхронизировать доступ к переменной из двух потоков? - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 19, средняя оценка - 4.79
Avazart
 Аватар для Avazart
6904 / 5144 / 253
Регистрация: 10.12.2010
Сообщений: 22,629
Записей в блоге: 17
15.05.2012, 20:48     Нужно ли синхронизировать доступ к переменной из двух потоков? #1
Допустим есть два потока: основной и вторичный.

1. И допустим есть глобальная переменная bool b;

Вопрос: является ли b разделяемым ресурсом? И нужно ли синхронизировать доступ к ней?
Например вариант когда b сигнализирует основному потоку о том что вторичный поток закончен...

2. Есть глобально объявленный std::vector. Вторичный поток переодически добовляет туда элементы.
Основной поток в это время выводит элементы на экран начиная с начала вектора ( вывод занимет определенное время так что вторичный поток обычно опережает работу основного).

Вопрос: Может ли возникнуть в таком случае проблемы? Например связанные с перераспределением памяти в векторе?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
15.05.2012, 20:48     Нужно ли синхронизировать доступ к переменной из двух потоков?
Посмотрите здесь:

Доступ к статической переменной-члену C++
Доступ к переменной по абсолютному адресу. C++
C++ Реализовать доступ к закрытой переменной
доступ к структурной переменной C++
C++ Доступ к переменной из разных файлов
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
-=ЮрА=-
Заблокирован
Автор FAQ
18.05.2012, 00:12     Нужно ли синхронизировать доступ к переменной из двух потоков? #2
Avazart, синхронизировать нужно!Без синхронизации каждый поток живёт своей жизнью, положим у тебя простая можель Производитель-Потребитель, производитель скажем генерирует числа и дописывает их в массив, а производитель увеличивает число элементов и производит реаллок памяти. Теперь смотри производитель работает на порядок быстрей клиента, т.к. аллокать память дольше чем генерировать число, вот и смотри ты либо будешь терять значения, либо если индексирование идёт в производителе ещё и выходить за области отведенной памяти.
Я за синхронизацию, как я понял твоя bool b глобальная, угадал?Плохой концепт - мы можем 300 раз переработать момент когда один поток изменит её значение, а второй отреагирует на это изменение.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
18.05.2012, 13:07     Нужно ли синхронизировать доступ к переменной из двух потоков? #3
Avazart, Сам подумай, что будет, если этот код начнет работать без синхронизации.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <iostream>
#include <boost/thread.hpp>
#include <vector>
#include <iterator>
#include <random>
 
bool number_in_process = false;
bool ended = false;
std::vector<int> numbers;
boost::mutex mutex;
boost::condition_variable cond;
const int max_size = 20;
 
void add_number(std::mt19937& gen, std::uniform_int_distribution<>& distr)
{
   while (!ended)
   {
      if (!number_in_process)
      {
         int value = distr(gen);
         numbers.push_back(value);
         number_in_process = true;
         std::cout << "Value: " << value << " in process: " << number_in_process << std::endl;
         cond.notify_all();
      }
   }
}
 
void print()
{
   boost::unique_lock<boost::mutex> lock(mutex);
   while (1)
   {
      if (number_in_process)
      {
         std::cout << "Numbers size: " << numbers.size() << " numbers: ";
         std::copy(numbers.begin(), numbers.end(), std::ostream_iterator<int>(std::cout, " "));
         std::cout << std::endl;
         number_in_process = false;
         if (numbers.size() == max_size)
         {
            ended = true;
            break;
         }
      }
      cond.wait(lock);
   }
}
 
int main()
{
   std::mt19937 gen(time(0));
   std::uniform_int_distribution<> distr(0, 25);
   boost::thread add_thread(add_number, gen, distr);
   boost::thread print_thread(print);
   add_thread.join();
   print_thread.join();
   std::cout << "Size: " << numbers.size() << std::endl;
}
Avazart
 Аватар для Avazart
6904 / 5144 / 253
Регистрация: 10.12.2010
Сообщений: 22,629
Записей в блоге: 17
18.05.2012, 17:43  [ТС]     Нужно ли синхронизировать доступ к переменной из двух потоков? #4
Производитель-Потребитель, производитель скажем генерирует числа и дописывает их в массив, а производитель увеличивает число элементов и производит реаллок памяти.
Не понял само предложение.

Добавлено через 1 час 33 минуты
Насчет vector я имел ввиду код типа
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//---------------------------------------------------------------
vector<int> v;
//---------------------------------------------------------------
DWORD WINAPI ThreadFunc(LPVOID param)
{
 for(int i=0;i<1000;i++) v.push_back(i);
}
//---------------------------------------------------------------
int _tmain(int argc, _TCHAR* argv[])
{
system("chcp 1251");
 
DWORD lpThreadId;
HANDLE hT= CreateThread(NULL,0,ThreadFunc,NULL,0,&lpThreadId);
 
Sleep(100); // задержка на 100 мс
for(int i=0;i<v.size();i++)
  {
  Sleep(100);// задержка на 100 мс
  cout<< v[i]<<endl;
  }
system("pause");
return 0;
}
//---------------------------------------------------------------------------
Добавлено через 9 минут
Про bool имел ввиду приблизительно такой код
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
using namespace std;
//---------------------------------------------------------------
bool b=false;
//---------------------------------------------------------------
DWORD WINAPI ThreadFunc(LPVOID param)
{
 // do something
 b=true;
}
//---------------------------------------------------------------
int _tmain(int argc, _TCHAR* argv[])
{
system("chcp 1251");
 
bool b=false;
DWORD lpThreadId1;
HANDLE hT1= CreateThread(NULL,0,ThreadFunc,NULL,0,&lpThreadId1);
 
// do something
 
if(b)// Если поток hT1 закончен запустить подобный поток ( допустим исх.данные изменились )
 {
 bool b=false;
 DWORD lpThreadId2;
 HANDLE hT2= CreateThread(NULL,0,ThreadFunc,NULL,0,&lpThreadId2);
 }
else
 {
  TerminateThread(hT1,NULL);//Если еще не закончин убиваем его
  bool b=false;
  DWORD lpThreadId2;  // Допустим запускаем поток с новыми исх данными
  HANDLE hT2= CreateThread(NULL,0,ThreadFunc,NULL,0,&lpThreadId2);
 }
system("pause");
return 0;
}
//---------------------------------------------------------------------------
Avazart
 Аватар для Avazart
6904 / 5144 / 253
Регистрация: 10.12.2010
Сообщений: 22,629
Записей в блоге: 17
06.06.2012, 10:26  [ТС]     Нужно ли синхронизировать доступ к переменной из двух потоков? #5
Вверх
Avazart
 Аватар для Avazart
6904 / 5144 / 253
Регистрация: 10.12.2010
Сообщений: 22,629
Записей в блоге: 17
18.08.2012, 19:32  [ТС]     Нужно ли синхронизировать доступ к переменной из двух потоков? #6
Нашел ответ на свой вопрос №1 насчет bool

В книге "С++ Сборник рецептов" стр 490 (там идет речь о boost::mutex)
Миниатюры
Нужно ли синхронизировать доступ к переменной из двух потоков?  
Pure
 Аватар для Pure
228 / 49 / 2
Регистрация: 13.03.2012
Сообщений: 453
Записей в блоге: 7
18.08.2012, 20:24     Нужно ли синхронизировать доступ к переменной из двух потоков? #7
Avazart, библиотека потоков реализована в новом стандарте, советую пользоваться ей а не привязываться к оси

ВОТ оно одинаково хорошо работает и в линуксе и в винде. Проверял.
Avazart
 Аватар для Avazart
6904 / 5144 / 253
Регистрация: 10.12.2010
Сообщений: 22,629
Записей в блоге: 17
18.08.2012, 21:05  [ТС]     Нужно ли синхронизировать доступ к переменной из двух потоков? #8
Вот только новый стандарт не во всех IDE.

Да и на винде нет особого смысла использовать boost, так как можно работать напрямую через WinApi.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
18.08.2012, 21:12     Нужно ли синхронизировать доступ к переменной из двух потоков? #9
Avazart, Ну шикарно. А еще есть pthread в Linux-е, думаете тоже нет особого смысла использовать boost? boost::thread это высокоуровневый интерфейс над низкоуровневым API, так же как и std::thread.
Avazart
 Аватар для Avazart
6904 / 5144 / 253
Регистрация: 10.12.2010
Сообщений: 22,629
Записей в блоге: 17
18.08.2012, 21:21  [ТС]     Нужно ли синхронизировать доступ к переменной из двух потоков? #10
Думаю не стоит молиться на кроссплатформенность...

Тем более что наверное в каждой среде есть свои нароботки по работе с потоками.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
18.08.2012, 23:00     Нужно ли синхронизировать доступ к переменной из двух потоков? #11
Avazart, Работа с потоками в API OS низкоуровнева. Высокоуровневая работа с потоками является крайне важным фактором, ибо мы пишем на С++, а не на сях.
Avazart
 Аватар для Avazart
6904 / 5144 / 253
Регистрация: 10.12.2010
Сообщений: 22,629
Записей в блоге: 17
18.08.2012, 23:02  [ТС]     Нужно ли синхронизировать доступ к переменной из двух потоков? #12
Так никто не мешает использовать свои классы как обвертки... или использовать готовые обвертки предоставляемые IDE
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
19.08.2012, 01:03     Нужно ли синхронизировать доступ к переменной из двух потоков? #13
Avazart, Ну даже не знаю. Писать свои велосипеды? Мало желания. Использовать обертки специфической IDE (типа QThread и чего-то там из MFC)? Как-то тоже. Если есть в бусте и стандарте - то буду пользоваться именно ими
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
19.08.2012, 01:09     Нужно ли синхронизировать доступ к переменной из двух потоков? #14
Цитата Сообщение от ForEveR Посмотреть сообщение
А еще есть pthread в Linux-е, думаете тоже нет особого смысла использовать boost?
я использую pthread for windows; это в мой огород камень?
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
19.08.2012, 01:16     Нужно ли синхронизировать доступ к переменной из двух потоков? #15
kravam, Ну изначально pthread все-таки для линукса.

Нет, я не говорю, что плохо использовать средства ОС или IDE, просто когда есть возможность желательно пользоваться стандартными либами (или бустом, если нет С++11).
Avazart
 Аватар для Avazart
6904 / 5144 / 253
Регистрация: 10.12.2010
Сообщений: 22,629
Записей в блоге: 17
19.08.2012, 01:17  [ТС]     Нужно ли синхронизировать доступ к переменной из двух потоков? #16
типа QThread
А что прикручивать буст ради потоков? Да предположу что у QThread больше возможностей чем в boost

boost- монстр... его проблема целиком проинсталить, а по частям под виндой ...
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
19.08.2012, 01:21     Нужно ли синхронизировать доступ к переменной из двух потоков? #17
Avazart, Да нет конечно. Если используешь Qt и не нужно что-либо еще - используй QThread. Если используешь MSVC - используй что-нибудь оттуда. Можешь так же использовать средства ОС (хотя это и не слишком удобно), в остальных случаях std::thread или boost::thread, т.к. дефакто std::thread в текущем стандарте, то использование его в своих проетах однозначно, использование где-то в коммерческих проектах требует раздумий.

boost- монстр... его проблема целиком проинсталить, а по частям под виндой ...
Он инсталируется долго - факт. Но вот то, что "проблема целиком проинсталить" категорически не согласен.
Avazart
 Аватар для Avazart
6904 / 5144 / 253
Регистрация: 10.12.2010
Сообщений: 22,629
Записей в блоге: 17
19.08.2012, 01:28  [ТС]     Нужно ли синхронизировать доступ к переменной из двух потоков? #18
Работа с потоками в API OS низкоуровнева. Высокоуровневая работа с потоками является крайне важным фактором, ибо мы пишем на С++, а не на сях.
Просматривал boost/thread мне показалась что возможности урезаны сильно...и что удобнее как раз обратное ...

Кстати boost/mutex как я понял не совсем мютекс? Т.е. он не действует среди процессов.

Как-то читал книгу в ней говорилась о причине того что С++ не потдерживает многопоточность дабы предоставить возможность более тесно и эффективно взаимодействовать с ОС
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
19.08.2012, 01:39     Нужно ли синхронизировать доступ к переменной из двух потоков? #19
Avazart, Для межпроцессорного взаимодействия есть boost::interprocess, boost::thread к этому никаким боком не относится. Возможно, однако сейчас многопоточность введена в стандарт.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.08.2012, 01:44     Нужно ли синхронизировать доступ к переменной из двух потоков?
Еще ссылки по теме:

C++ Доступ к переменной только из двух функций. Возможно ли это?
C++ Доступ к переменной из другого модуля
Самый простой способ реализации двух параллельных потоков C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Avazart
 Аватар для Avazart
6904 / 5144 / 253
Регистрация: 10.12.2010
Сообщений: 22,629
Записей в блоге: 17
19.08.2012, 01:44  [ТС]     Нужно ли синхронизировать доступ к переменной из двух потоков? #20
Ну тогда это не соответствует назнанию в Win да и помойму в Linux, мютекс действует между процессами тем он и отличается от критических секций.
Yandex
Объявления
19.08.2012, 01:44     Нужно ли синхронизировать доступ к переменной из двух потоков?
Ответ Создать тему
Опции темы

Текущее время: 12:14. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru