Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.67/15: Рейтинг темы: голосов - 15, средняя оценка - 4.67
Эксперт С++
8379 / 6115 / 613
Регистрация: 10.12.2010
Сообщений: 28,550
Записей в блоге: 30
1

Объекты синхронизации

02.07.2012, 22:31. Показов 3085. Ответов 11
Метки нет (Все метки)

Пишу https://www.cyberforum.ru/blogs/131347/

Есть std::deque<T> - разделяемый между:
1. Главным потоком который может обращатся к объекту типа T и отображать его в компонентах...( по действию пользователя)
2. Вспомогательным потоком который переодически может читать и добавлять новые объекты типа T в начало этого дека

Вопрос: что выбрать в качестве объекта синхронизации в данном случае? Что лучше подходит?

Добавлено через 2 часа 50 минут
Решил пока через мютекс.
Итого появился тест-пример:
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
//----------------Мютекс и Поток---------------------------------------------
HANDLE hMutex,hThread =NULL;
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{          // создать мютекс
hMutex = CreateMutex(NULL,false,"mutex");
}
//------------------- Ф-ция потока -------------------------------------------
DWORD WINAPI ThreadFunc(LPVOID)
{
while(true)
 {
  int code = WaitForSingleObject(hMutex,10);// проверить-занять мютекс(ожидание 10мс)
 
  if(code == WAIT_TIMEOUT )    ShowMessage("Превышено время для потока");
  if(code == WAIT_OBJECT_0)    ShowMessage("Успешно занят потоком");
 
  Sleep(10000);
  ReleaseMutex(hMutex); // Освободить мютекс
  Sleep(10000);
 }
return 0;
}
//------------------ Начать поток  --------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
if(!hThread)
 {
  DWORD lpThreadId;
  hThread= CreateThread(NULL,0,ThreadFunc,NULL,0,&lpThreadId);
 }
}
//----------------- Проверить доступность мютекса ---------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
int code = WaitForSingleObject(hMutex,10);
 
if(code == WAIT_TIMEOUT)
 {
  ShowMessage("Превышено время для кнопки");
  return;
 }
if(code == WAIT_OBJECT_0) ShowMessage("Успешно занять через кнопку");
}
//----------------- Освободить мютекс ---------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
ReleaseMutex(hMutex);
}
//---------------------------------------------------------------------------
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
02.07.2012, 22:31
Ответы с готовыми решениями:

Как работают объекты синхронизации (критическая секция, мьютекс, событие, семафор)?
Помогите пожалуйста разобраться!Как должны работать объекты синхронизации такие как:критическая...

Вопрос по синхронизации
Пишу сетевую игрушку, вот возник вопрос 1. У меня есть контейнер типа map из STL в котором...

Потоки, TThread, нет синхронизации
Доброго дня, товарищи программисты. Проблемка тут у меня с потоком. Я создаю поток, делаю там...

Переделать программу, чтобы она выполнялась без использования примитива синхронизации Mutex
Необходимо переделать программу так, чтобы она выполнялась без использования примитива...

11
Модератор
3332 / 2116 / 343
Регистрация: 13.01.2012
Сообщений: 8,244
02.07.2012, 22:47 2
критические секции вроде быстрее. а событий превышения времени ожидания быть не должно по определению.
0
Эксперт С++
8379 / 6115 / 613
Регистрация: 10.12.2010
Сообщений: 28,550
Записей в блоге: 30
02.07.2012, 22:58  [ТС] 3
а событий превышения времени ожидания быть не должно по определению.
Не понял...
Почему это?
То есть как реализовать через мютекс без WaitForSingleObject()

Добавлено через 8 минут
По поводу крит.секций ищу что почитать, пока нашел
http://www.cyberguru.ru/progra... page2.html
0
Модератор
3332 / 2116 / 343
Регистрация: 13.01.2012
Сообщений: 8,244
02.07.2012, 23:45 4
как реализовать через мутекс без вэйт - не знаю. не должно - потому что это ненормально когда какойто поток захватил ресурс и не отдает. как правило - это крах программы в любом случае - отслеживаете вы данный момент или нет. поэтому такого не должно происходить.
с крит секциями все просто - гденибудь наверху инициализируем, если хотим захватить - входим, когда возвращаем - выходим, после отработки гденибудь наверху убиваем.
0
Эксперт С++
8379 / 6115 / 613
Регистрация: 10.12.2010
Сообщений: 28,550
Записей в блоге: 30
03.07.2012, 00:02  [ТС] 5
ненормально когда какойто поток захватил ресурс и не отдает.
Согласен но...
Ну не может же он моментально отдать ресурс ему нужно завершить свои действия до логического конца и только потом отдать.

Но согласен если время подобрано правильно то :
C++
1
if(code == WAIT_TIMEOUT )    ShowMessage("Превышено время для потока");
это уже можно сказать обработка исключения-ошибки

Добавлено через 6 минут
если хотим захватить - входим
А если ресурс занят, то поток ждет?
0
Модератор
3332 / 2116 / 343
Регистрация: 13.01.2012
Сообщений: 8,244
03.07.2012, 10:33 6
если кто-то вошел в секцию, то другой, который тоже пытается войти в эту же секцию останавливается (в функции входа) и ждет пока первый выйдет.
1
Эксперт С++
8379 / 6115 / 613
Регистрация: 10.12.2010
Сообщений: 28,550
Записей в блоге: 30
03.07.2012, 23:49  [ТС] 7
Тест-пример:
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
CRITICAL_SECTION cs;
int a[5];
//----------------Поток----------------------
HANDLE hT =NULL;
//------------------------------------------------------
DWORD WINAPI ThreadFunc(LPVOID)
{
int i, num = 0;
 
while (true)
 {
   EnterCriticalSection( &cs );
        for ( i = 0; i < 5; i++ ) a[i] = num;
   LeaveCriticalSection( &cs );
   num++;
 }
return 0;
}
//------------------------------------------------------
int _tmain(int argc, _TCHAR* argv[])
{
InitializeCriticalSection( &cs );
 
DWORD lpThreadId;
hT= CreateThread(NULL,0,ThreadFunc,NULL,0,&lpThreadId);
 
while(true)
 {
   EnterCriticalSection( &cs );
         printf( "%d %d %d %d %d\n",a[0], a[1], a[2],a[3],a[4]);
   LeaveCriticalSection( &cs );
 }
 
return 0;
}
//---------------------------------------------------------------------------
http://www.cyberguru.ru/progra... page2.html

Добавлено через 2 минуты
Только вот этого я не вижу:
отработки гденибудь наверху убиваем.
Добавлено через 15 минут
Забыли наверное
C++
1
DeleteCriticalSection( &cs );
0
1 / 1 / 0
Регистрация: 06.02.2013
Сообщений: 12
06.02.2013, 12:45 8
Добрый день. Новичок на форуме и в теме, не пинайте сильно.
Для синхронизации двух потоков использую мьютекс. После запуска второй нити создаю мьютекс.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void __fastcall mythread::Execute()
{
    //---- Place thread code here ----
    HANDLE hThreadHandle;
 
    hThreadHandle = CreateMutex(NULL, true, "MY");
 
    while(!this->Terminated)
    {
        pMyModule->ReceiveMsg();
    }
 
    ReleaseMutex(hThreadHandle);
    CloseHandle(hThreadHandle);
}
В pMyModule->ReceiveMsg() по команде из основной нити открываю мьютекс вот таким образом
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
if(this->bWaitForMessage)
    {
        this->hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "MY");
 
        if(this->hMutex == NULL)
        {
            // Не удалось создать мьютекс
                        while(1);    
        }
 
        this->bWaitForMessage = false;
        this->bReceivingMessage = true;
    }
Мьютекс открывается, но не с тем номером, с которым я его создал (смотрю в отладчике). Хотя ошибок при открытии нет. И код в основной нити не видит, что мьютекс занят другой нитью.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
while(this->bWaitForMessage); // Ожидание завершения обработки второй нитью 
switch(WaitForSingleObject(this->hMutex, TimeoutMs))
    {
        case WAIT_OBJECT_0:
            Result = RCV_OK; // Всегда оказываемся здесь
            break;
 
        case WAIT_TIMEOUT:
            Result = RCV_TIMEOUT;
            break;
 
        case WAIT_FAILED:
            Result = RCV_FAULT;
            break;
 
        case WAIT_ABANDONED:
            Result = RCV_FAULT;
            break;
 
        default:
            //ShowMessage("Default");
            break;
Пробовал изменить имя открываемого мьютекса, тогда при открытии возвращает NULL как и положено, то есть имена правильно задал.
Возможно я не правильно понимаю механизм работы мьютексов, поставьте на путь истины.
0
Эксперт С++
8379 / 6115 / 613
Регистрация: 10.12.2010
Сообщений: 28,550
Записей в блоге: 30
06.02.2013, 12:59  [ТС] 9
Для синхронизации потоков лучше использовать критические секции они проще и быстрее.

Добавлено через 5 минут
Единственно думаю что не предусмотрел в предыдущем коде это отлов исключений из-за чего может быть deadlock

C++
1
2
3
4
5
6
7
8
9
10
   EnterCriticalSection( &cs );
   try{ 
        for ( i = 0; i < 5; i++ ) a[i] = num;
       }
   catch(...)
       {
         //...
         LeaveCriticalSection( &cs );
       }
   LeaveCriticalSection( &cs );
0
1 / 1 / 0
Регистрация: 06.02.2013
Сообщений: 12
06.02.2013, 13:08 10
Цитата Сообщение от Avazart Посмотреть сообщение
Для синхронизации потоков лучше использовать критические секции они проще и быстрее.
Хотелось бы понять, что с мьютексами не так, уже второй день бьюсь. У меня задача такая, есть метод класса, который постоянно "выгребает" данные из буфера (данные с USB устройства). Он вызывается из второй нити, в основной нити делается отправка запроса в устройство (устанавливается флаг, вторая нить обрабатывает его, открывает ранее созданный мьютекс и сбрасывает флаг), основная нить ждет сброса флага второй нитью (зацикливается), после чего вызывает WaitForSingleObject и ждет освобождения мьютекса. Если мьютекс освободился в заданный интервал времени, значит принят ответ, если вышла по таймауту, то ответ не пришел. Проблема в том, что функция всегда возвращает значение WAIT_OBJECT_0. Словно этот мьютекс не захвачен второй нитью.
0
Эксперт С++
8379 / 6115 / 613
Регистрация: 10.12.2010
Сообщений: 28,550
Записей в блоге: 30
06.02.2013, 13:19  [ТС] 11
Ну попробуйте код что в первом посте и сравните...

Честно говоря я уже не помню как оно там работает, но про объекты синхронизации(в том числе мютекс) можно почитать в Архангельском "... Builder6 и 2006"
1
1 / 1 / 0
Регистрация: 06.02.2013
Сообщений: 12
06.02.2013, 13:46 12
Кажись догадался в чем дело, сейчас проведу эксперимент.

Добавлено через 13 минут
Цитата Сообщение от Avazart Посмотреть сообщение
Ну попробуйте код что в первом посте и сравните...

Честно говоря я уже не помню как оно там работает, но про объекты синхронизации(в том числе мютекс) можно почитать в Архангельском "... Builder6 и 2006"
Спасибо за наводку, дело оказалось в моем не верном восприятии работы с мьютексами. В моем случае после открытия нужно "занять" мьютекс функцией WaitForSingleObject. А я думал, открытие "занимает" его. По этому основная нить всегда беспрепятственно "занимала" мой мьютекс.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
06.02.2013, 13:46

При синхронизации функции из потока возникает ошибка: "Out of memory"
Доброго времени суток. Есть код:...

Объекты синхронизации
Доброй ночи всем обитателям этого форума. Нужна помощь с лабораторной работой по Объектам...

Объекты синхронизации WIN32
Если кто встречался с чем-то подобным, не могли бы привести пример такого кода пожалуйста: ...

Объекты синхронизации. мьютексы, семафоры
помогите пожалуйста. . Реализовать на семафоре мьютекс. Количественные характеристики мьютекса...


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

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.