![]() |
|
Модераторы: Partizan, gambit |
![]()
|
|
| Гость_ser |
|
||||||
|
Unregistered |
два потока и стек типа FIFO: один запиcывает в буфер каждую ms. простой обект типа int, другой считывает из него. вроде Queue как нельзя лучше подходит для этого случая.
|
||||||
|
|||||||
| Domestic Cat |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5452 Регистрация: 3.5.2004 Где: Dallas, US Репутация: 9 Всего: 172 |
Я не совсем понял чего ты хочешь сделать, подробнее плиз.
-------------------- |
|||
|
||||
| Guest |
|
|||
|
Unregistered |
в первом потоке я запиcываю в буфер Queue значение типа int.
во втором потоке считываю из этого буфера значение стоящее в очереди первым (FIFO). как я понимаю после чтения посредством Dequeue это значение из очереди удаляется, что мне и надо. |
|||
|
||||
| Domestic Cat |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5452 Регистрация: 3.5.2004 Где: Dallas, US Репутация: 9 Всего: 172 |
Тогда сразу для ФАКа - будьмо надеяться что добрые боги этого форума сжалятся :}
----------------------------------------------------------------------------------------------------------- Синхронизация потоков по .NETовски Есть один стандартный пример о синхронизации потоков, используемый во многих книжках - задача о производителе и потребителе (Producer и Consumer). Первый чего-нибудь производит, второй потребляет. Поскольку оба по жизни люди независимые, то и описываются они двумя различными тредами. Основная проблема в том, что оба имеют дело с одним и тем же объектом - продуктом. Ели мы запустим 2 треда, н заботясь о синхронизации, то столкнемся с ситуацией когда потребитель попытается пользоваться товаром, который еще не произведен (в реале он повернется и уйдет, а у нас будет брошен нехороший иксепшн); или находится в процессе производства ( такое вообще представить трудно в жизни, в программе же баг такой можно долго ловить). В жизни таких плохих вещей не происходит потому, что производитель дает понять потребителю что товар произведен и его можно покупать / потреблять. Например, рекламой по телевизору... каждые 15 минут... В .NET / Java дело происходит точно так же. Рассмотрим пример с производителем пива, и потребителем, который не хочет пить менее 10 ящиков пива за раз и требует чтобы пиво было подано в том порядке, в каком оно было произведено. Как решить проблему? Естественно, нужно использовать Queue, хранящую ящики пива. Вопрос в том, как избавиться от двух нехороших вещей - потребителя, получающего пустую Queue или неполную Queue? Вместо длинного размусоливания и подведения к логическому концу, приведу сразу решение :
Ну во-первых мы считаем, что для того, чтобы поизвести / выпить ящик пива требуется 5 мс. Далее пойдем по решению. В конструкторе создается 2 треда. Далее эти треды запускаются в случайном порядке. Что делает Производитель. 1. Заходит в метод Producer. 2. Пытается забрать объект SyncRoot у beer. Тут возможны 2 ситуации: 2.а. Этот объект свободен (Потребитель еще не начал выполнять свой метод). Тогда Производитель забирает лок и блокирует Потребителю вход в Блок 2. 2.б. Этот объект занят (отобран Потребителем). Производитель ждет снаружи Блока 1. Далее продолжаем оба варианта по отдельности, начинаем с 2.а. --3.а. Производитель начинает производить пиво. Если теперь Потребитель попытается войти в Блок 2, он вынужден будет ждать снаружи, т.к. у него нет лока SyncRoot . 4.а. Производитель производит пиво, меняет флаг isBeerReady и вызывает Мonitor.PulseAll() (оба ничего в данном случае не делают), и высвобождает лок. 5.а. Истомленный жаждой Потребитель наконец получает лок, пропускает цикл и выпивает все. --- 3.б. А что если первым лок получил Потребитель? С тредами ничего заранее не известно, даже если бы я не использовал рандом а четко указал какой тред запускается первым, все равно неизвестно как бы легла рука планировщика и какой бы слайс времени она бы отрезала каждому из тредов. Итак, Потребитель получает лок. Но isBeerReady == false и Потребитель попадает в бесконечный цикл. А лок-то у него, и потому Производитель так бы и остался навечно ждатЬ доступа к локу, если бы не Monitor.Wait. Этот метод заставляет Потребителя отпустить лок и остановиться. 4.б. Теперь Производитель получает доступ к Блоку 1 и производит пиво. Перед самым завершением работы он уведомляет всех ждущих на объекте SyncRoot (то есть Потребителя) что усе готово - методом Monitor.PulseAll. 5. б. Потребитель просыпается и спокойно потребляет пиво. -------------------- |
|||
|
||||
| Guest |
|
|||
|
Unregistered |
после того как закомментировал блокировку lock(...) во втором потоке, (все остальное оставил как есть) похоже что все работает без потерь (если не принимать во внимание CPU Usage=95% и готовность проц. блока на взлет от надрывной работы вентилятора процессора). Почему что-то работает, обяснить не могу, ибо скопировал куски из примеров майкрософта и подозреваю что перемудрил с синхронизацией на каждой итерации записи. Может есть механизм попроще?
|
|||
|
||||
| Guest |
|
|||
|
Unregistered |
извини, не заметил сообщения выше. сейчас почитаю, переварю
|
|||
|
||||
| -ser- |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 344 Регистрация: 1.2.2005 Репутация: 5 Всего: 13 |
за пример спасибо, классика. но один важный вопрос для моего конкретного случая.
у меня старая добрая соц. система с 5-ти летним планом, для выполнения которого производитель обязан варить и отгружать пиво в три смены БЕЗ ОСТАНОВКИ независимо от поставщика. перепроизводство не его забота. не получится ли в нашем случае так, что если машина заказчика со свежеотгруженным продуктом по каким-то причинам застряла на проходной на больше чем положенное время, то у нас встанет весь конвейер, сорвем пятилетку. Боюсь, что наивысший приоритет для Поставщика и наинизший для Заказчика не помогут. Это сообщение отредактировал(а) -ser- - 1.2.2005, 11:11 -------------------- "Тонкая, однако, работа." |
|||
|
||||
| Domestic Cat |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5452 Регистрация: 3.5.2004 Где: Dallas, US Репутация: 9 Всего: 172 |
Wait заставляет Потребителя выпустить лок, потому такая ситуация невозможна (по крайней мере в этом примере). Для более сложных вариантов решается все аналогично, хотя и поднапрячься нужно -------------------- |
|||
|
||||
| -ser- |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 344 Регистрация: 1.2.2005 Репутация: 5 Всего: 13 |
насколько я понял Wait потребителя для случая когда на складе пусто, а я имел ввиду задержку в цикле for Потребителя? может я что-то не понимаю. ладно буду пробовать. во всяком случае примерчик неплохой.
-------------------- "Тонкая, однако, работа." |
|||
|
||||
| Domestic Cat |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5452 Регистрация: 3.5.2004 Где: Dallas, US Репутация: 9 Всего: 172 |
Ааа ну так смо собой, если Производителю нужно работать с минимальными перерывами, то Потребитель бы просто упер себе все что тот произвел А для конкретной ситуации если что - пости, и там будем смотреть. -------------------- |
|||
|
||||
![]()
|
| Прежде чем создать тему, посмотрите сюда: | |
|
|
Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов. Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :) Так же не забывайте отмечать свой вопрос решенным, если он таковым является :) Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |