Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 23.11.2011, 22:45   #1
LockHeart
Пользователь
 
Регистрация: 23.10.2011
Сообщений: 14
По умолчанию winapi, использование Mutex'ов

Два вопроса, оба постараюсь тут уместить, чтобы не плодить темы...

Первое. Недавно пытался синхронизировать три потока при помощи мьютексов

Код:
DWORD WINAPI func1()
{
	for (int i = 0; i < 10000; i++)
	{
		WaitForSingleObject(hMutex1, INFINITE);
		Move[1] =  rand()%3;
		SetEvent(hMutex2);
	}
return 0;
}
DWORD WINAPI func2()
{
	for (int i = 0; i < 10000; i++)
	{
		WaitForSingleObject(hMutex2, INFINITE);
		Move[1] =  rand()%3;
		SetEvent(hMutex3);
	}
return 0;
}
DWORD WINAPI func3()
{
	for (int i = 0; i < 10000; i++)
	{
		WaitForSingleObject(hMutex3, INFINITE);
		Move[1] =  rand()%3;
		SetEvent(hMutex1);
	}
return 0;
}
Добрые люди подсказали, что мьютексы таким образом использовать нельзя, они привязаны к самим потокам и освобождать/занимать их нужно в одном и том же потоке. Хотелось бы уточнить, насколько это близко к правде и где про это можно почитать... пробежался по статейке о мьютексах в MSDN и не нашел там точного указания, что "вот так делать нельзя". А с меня очень просят именно так и ткнуть в какую-нибудь уважаемую литературу)

И второй вопрос. В приведенном выше примере была попытка сделать так, чтобы каждый поток генерировал случайные числа от 1 до 3 ( srand(time(NULL)); находится в WinMain). В таком виде ничего не получалось (я прикручивал запись в файлик полученного числа после каждой генерации, и по данным из файла стало ясно, что программа либо генерировала одно и то же тысячами, либо в массиве вообще оставались нули.). Помогло вынесение всех рандомов в отдельную функцию, которую эти потоки вызывают

Код:
void generate()
{
	a = rand()%3;
	b = rand()%3;
	c = rand()%3;
}
(значениям массива затем присваиваются эти a,b и c), однако, как выяснилось, генерируемая последовательность постоянна - два раза запускаем программу, в файл записываются 10.000 итераций, причем сгенерированные последовательности идентичны, хотя рандом вроде привязан к time(NULL). Подскажите, что не так? И как можно сделать более или менее правдоподобный рандом, не используя srand(time(NULL))?
LockHeart вне форума Ответить с цитированием
Старый 23.11.2011, 23:10   #2
_Ч_
Форумчанин
 
Регистрация: 07.01.2010
Сообщений: 141
По умолчанию

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

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

Последний раз редактировалось rpy3uH; 24.11.2011 в 08:20.
_Ч_ вне форума Ответить с цитированием
Старый 24.11.2011, 08:36   #3
rpy3uH
добрый няша
Старожил
 
Аватар для rpy3uH
 
Регистрация: 29.10.2006
Сообщений: 4,804
По умолчанию

Цитата:
Сообщение от LockHeart Посмотреть сообщение
Первое. Недавно пытался синхронизировать три потока при помощи мьютексов

Добрые люди подсказали, что мьютексы таким образом использовать нельзя, они привязаны к самим потокам и освобождать/занимать их нужно в одном и том же потоке. Хотелось бы уточнить, насколько это близко к правде и где про это можно почитать... пробежался по статейке о мьютексах в MSDN и не нашел там точного указания, что "вот так делать нельзя". А с меня очень просят именно так и ткнуть в какую-нибудь уважаемую литературу)
с мьютексами работай как-хочешь, хоть в 10 потоках с 15 мьютекасми в каждом, главное чтобы всё нормально работало и не было мёртвых захватов. а по самой работе с мьютеками лучше получше изучи мат.часть, например, надо использовать ReleaseMutex для освобождения мьютекса.

Цитата:
Сообщение от LockHeart Посмотреть сообщение
И второй вопрос. В приведенном выше примере была попытка сделать так, чтобы каждый поток генерировал случайные числа от 1 до 3 ( srand(time(NULL)); находится в WinMain). В таком виде ничего не получалось (я прикручивал запись в файлик полученного числа после каждой генерации, и по данным из файла стало ясно, что программа либо генерировала одно и то же тысячами, либо в массиве вообще оставались нули.). Помогло вынесение всех рандомов в отдельную функцию, которую эти потоки вызывают

(значениям массива затем присваиваются эти a,b и c), однако, как выяснилось, генерируемая последовательность постоянна - два раза запускаем программу, в файл записываются 10.000 итераций, причем сгенерированные последовательности идентичны, хотя рандом вроде привязан к time(NULL). Подскажите, что не так? И как можно сделать более или менее правдоподобный рандом, не используя srand(time(NULL))?
надо использовать srand(GetTickCount())

также рекомендую прочитать вот это
rpy3uH вне форума Ответить с цитированием
Старый 24.11.2011, 09:21   #4
Warn
Форумчанин
 
Аватар для Warn
 
Регистрация: 03.11.2011
Сообщений: 230
По умолчанию

Цитата:
Недавно пытался синхронизировать три потока при помощи мьютексов
Насколько мне известно мьютекс работает на уровне ядра системы, т.е. его стояния можно передавать/менять между процессами(программами) что сказывается на его производительности. Т.е. если выходить за пределы процесса не надо лучше использовать критические секции они на порядок быстрее работают.

мьютексы и секции
Вложения
Тип файла: txt Mutex.cpp.txt (2.9 Кб, 209 просмотров)
Тип файла: txt criticalsection.cpp.txt (2.1 Кб, 161 просмотров)
Warn вне форума Ответить с цитированием
Старый 24.11.2011, 14:45   #5
LockHeart
Пользователь
 
Регистрация: 23.10.2011
Сообщений: 14
По умолчанию

Цитата:
Сообщение от rpy3uH Посмотреть сообщение
например, надо использовать ReleaseMutex для освобождения мьютекса.
Когда с мьютексами прога отказалась выдавать нормальные результаты, переделал ее под Event'ы. Когда код сюда копировал, забыл SetEvent на ReleaseMutex обратно поменять... В программе с релиз-мьютексом было изначально)

Цитата:
Сообщение от rpy3uH Посмотреть сообщение
надо использовать srand(GetTickCount())

также рекомендую прочитать вот это
С GetTickCount попробовал, все равно такая же ситуация... За ссылочку спасибо, почитаю)

Последний раз редактировалось rpy3uH; 24.11.2011 в 15:00.
LockHeart вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
WinApi+C# Dimarik C# (си шарп) 13 20.04.2011 20:05
Qt vs. WinAPI Зелёный_спец Общие вопросы C/C++ 3 12.03.2010 15:34
Использование динамического массива в функции ReadFile (WinAPI). Korrado Помощь студентам 7 29.11.2009 13:38