Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.72/25: Рейтинг темы: голосов - 25, средняя оценка - 4.72
197 / 166 / 19
Регистрация: 05.05.2013
Сообщений: 1,228
1

Доступ к очереди из разных потоков

25.06.2015, 13:49. Показов 4848. Ответов 11

Подскажите по многопоточности, у меня есть очередь (Queue) и мне надо организовать к ней доступ из разных потоков, выискал несколько решений, одно из них использовать ключевое слово lock, а так же можно использовать классы Mutex, Monitor, возник вопрос при использовании Monitor, Monitor.Enter блокирует потоки пока не будет выполнен код между ним и Monitor.Exit, собственно вопрос, а зачем тогда метод Monitor.TryEnter? может быть такое что Monitor.Enter не сможет заблокировать поток? или как или что?
Так же что то подобное я встречал классе ConcurrentQueue, в частности метод TryDequeue.

так же еще такой вопрос, когда я пытаюсь заблокировать потоки что бы выполнить код в одном из потоков, например:

C#
1
2
3
4
5
6
7
8
9
lock(lockObj) {
    string temp = data.Dequeue();
}
 
// или 
 
Monitor.Enter(lockObj);
string temp = data.Dequeue();
Monitor.Exit(lockObj);
у меня сразу блокируются все остальные потоки или только тогда, когда эти другие потоки дойдут до конструкции lock или Monitor.Enter?

если не понятно, на примере, допустим я получаю HTML код странницы и далее в конструкции lock я эти данные помещаю в Queue, я начал получать HTML и тут вдруг блокировка потока, вроде как такое может закончится не корректно или потоки остановятся когда дойдут до конструкции lock?

Добавлено через 5 минут
читал msdn и еще некоторые источники но то ли я тупой то ли там очень скудное описание всего это.
0

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
25.06.2015, 13:49
Ответы с готовыми решениями:

Организовать доступ к элементам очереди из двух потоков
1 поток добавляет элементы в очередь. 2 дргуих должны счиать кждый элемент очереди. Как наилучшим...

Доступ к стриму из разных потоков
Задача такая, имеем мемористрим, в одном потоке постоянно пишем его. В другом потоке необходимо по...

Обезопасить доступ к коллекции из разных потоков
станет ли безопасным метод AddSafe? public static MyCollection myCol = new MyCollection(); ...

Доступ к БД с разных потоков
как реализовать доступ к одной базе данных с разных потоков? когда один сервер обрабатывает...

11
Эксперт .NET
15042 / 11395 / 2994
Регистрация: 17.09.2011
Сообщений: 19,113
25.06.2015, 14:04 2
Цитата Сообщение от VLK Посмотреть сообщение
а зачем тогда метод Monitor.TryEnter?
Для попытки взять право на пользование общим ресурсом без блокировки текущего потока.

Цитата Сообщение от VLK Посмотреть сообщение
может быть такое что Monitor.Enter не сможет заблокировать поток?
Конечно может — если ресурс не занят другим потоком, то блокировки текущего не будет.

Цитата Сообщение от VLK Посмотреть сообщение
когда я пытаюсь заблокировать потоки что бы выполнить код в одном из потоков, у меня сразу блокируются все остальные потоки или только тогда, когда эти другие потоки дойдут до конструкции lock или Monitor.Enter?
Когда дойдут до конструкции при условии, что lockObj ссылается на один и тот же объект.

Цитата Сообщение от VLK Посмотреть сообщение
допустим я получаю HTML код странницы и далее в конструкции lock я эти данные помещаю в Queue, я начал получать HTML и тут вдруг блокировка потока, вроде как такое может закончится не корректно или потоки остановятся когда дойдут до конструкции lock?
Зависит от того, какие участки кода вы блокируете для других потоков.
1
197 / 166 / 19
Регистрация: 05.05.2013
Сообщений: 1,228
25.06.2015, 14:16  [ТС] 3
Цитата Сообщение от kolorotur Посмотреть сообщение
Для попытки взять право на пользование общим ресурсом без блокировки текущего потока.
Цитата Сообщение от kolorotur Посмотреть сообщение
Конечно может — если ресурс не занят другим потоком, то блокировки текущего не будет.

хм.. а разве оно не работает по принципу что запускается метод Monitor.Enter и его выполнение будет закончено ровно тогда, когда для его потока наступит очередь, ну т.е. короче, есть 15 потоков, допустим 5-й поток доходит до Monitor.Enter но сейчас выполняются другие потоки по этому 5-й поток пока стоит в ожидании, а именно ожидание происходит в методе Monitor.Enter, когда только наступит очередь 5-го потока, тут же будет завершен вызов Monitor.Enter 5-го потока и будет выполнятся код между Monitor.Enter и Monitor.Exit

Я не знаю, но просто по логике вроде как так должно быть, правда зачем тогда два метода, они взаимоисключающие.
0
Эксперт .NET
15042 / 11395 / 2994
Регистрация: 17.09.2011
Сообщений: 19,113
25.06.2015, 14:26 4
Цитата Сообщение от VLK Посмотреть сообщение
запускается метод Monitor.Enter и его выполнение будет закончено ровно тогда, когда для его потока наступит очередь
Да, только не используйте слово "очередь" — там очереди в понимании "первый пришел — первый получил" нет.
Если ресурс не занят или только что освободился, то следующим его может захватить любой из 14-и ждущих потоков.

Цитата Сообщение от VLK Посмотреть сообщение
по логике вроде как так должно быть
Так и есть!

Цитата Сообщение от VLK Посмотреть сообщение
зачем тогда два метода, они взаимоисключающие.
Почему взаимоисключающие?
Monitor.Enter — попытаться взять права на использование ресурсом, если ресурс занят — ждать, пока не освободится.
Monitor.TryEnter — попытаться взять права на использование ресурсом, если занят — вернуть false, если был свободен и сейчас занят мной, то вернуть true. В любом случае продолжать дальнейшую работу.

Вроде никакого взаимоисключения.
1
197 / 166 / 19
Регистрация: 05.05.2013
Сообщений: 1,228
25.06.2015, 14:43  [ТС] 5
Цитата Сообщение от kolorotur Посмотреть сообщение
Почему взаимоисключающие?
а, то есть различие их примерно такое (по логике), Enter если участок кода занят, жди пока освободится, а у TryEnter если участок кода НЕ занят, выполнял, а если занят, можешь пока что то другое сделать, ну и в коде это выглядит как то так:
C#
1
2
3
4
5
6
7
8
9
if (Monitor.TryEnter(lockObj))
{
    // не занято, выполняй
    Monitor.Exit(lockObj);
}
else
{
    // пока занято, сделаю что то еще
}
так?
0
Эксперт .NET
15042 / 11395 / 2994
Регистрация: 17.09.2011
Сообщений: 19,113
25.06.2015, 14:52 6
Лучший ответ Сообщение было отмечено VLK как решение

Решение

Цитата Сообщение от VLK Посмотреть сообщение
так?
Так, только правильная семантика не "пока занято, сделаю что-то другое", а "раз уж занято, то буду делать что-то другое".
Первое подразумевает, что как только ресурс освободится, выполнение автоматом перепрыгнет в блок "не занято, выполняй".
На деле же, если в вашем коде ресурс занят, то блок "не занято, выполняй", будет просто пропущен. Чтобы его выполнить, вам придется самим кодить возвращение к этому блоку, например помещая условие в цикл.
1
197 / 166 / 19
Регистрация: 05.05.2013
Сообщений: 1,228
25.06.2015, 15:02  [ТС] 7
можно еще такой вопрос, по теме, а вот какие еще классы и ключевые слова существуют для работы с многопоточностью, я знаю о lock, классы Thread, Task, Monitor, Mutex, Semaphore, Interlocked, Parallel ну и я читал про async и await методы.
может есть какая статья, где был описывались все средства для работы с многопоточностью?
0
Эксперт .NET
15042 / 11395 / 2994
Регистрация: 17.09.2011
Сообщений: 19,113
25.06.2015, 15:07 8
Цитата Сообщение от VLK Посмотреть сообщение
а вот какие еще классы и ключевые слова существуют для работы с многопоточностью? может есть какая статья, где был описывались все средства для работы с многопоточностью?
Все классы описаны в документации, достаточно глянуть описание пространства System.Threading.
Тыкая на каждый класс можно посмотреть его описание, применение и пример использования.

Цитата Сообщение от VLK Посмотреть сообщение
может есть какая статья, где был описывались все средства для работы с многопоточностью?
Как правило в книжках по программированию описывают различные подходы для решения различных задач.
Мне очень нравится серия "C# In a Nutshell" братьев Альбахари.
1
197 / 166 / 19
Регистрация: 05.05.2013
Сообщений: 1,228
25.06.2015, 17:27  [ТС] 9
kolorotur, еще такой вопрос забыл уточнить, если я в одном месте использую
C#
1
2
3
lock(lockObj) {
    // ....
}
а в другом:
C#
1
2
3
Monitor.Enter(lockObj);
string temp = data.Dequeue();
Monitor.Exit(lockObj);
но объект lockObj общий, это нормально будет работать?
0
Эксперт .NET
15042 / 11395 / 2994
Регистрация: 17.09.2011
Сообщений: 19,113
25.06.2015, 19:27 10
VLK, да, главное не мешайте их в одном блоке.

lock — это синтаксический сахар для Monitor.Enter/Exit, конструкция lock(obj) { ... } разворачивается компилятором примерно в такую:
C#
1
2
3
4
5
6
7
8
9
Monitor.Enter(obj);
try
{
   ...
}
finally
{
   Monitor.Exit(obj);
}
1
197 / 166 / 19
Регистрация: 05.05.2013
Сообщений: 1,228
14.08.2015, 12:24  [ТС] 11
kolorotur, еще такой вопрос возник

C#
1
2
3
4
5
6
7
8
9
10
11
12
List<int> temp = new List<int>();
 
// ....
//  в потоках:[
 
for (int i = 0; i < 100; i++)
{
    Monitor.Enter(temp);
    if (i == 50) break;
    temp.Add(temp.Count);
    Monitor.Exit(temp);
}
я делаю break до Monitor.Exit, все закончится печально?
0
Эксперт .NET
15042 / 11395 / 2994
Регистрация: 17.09.2011
Сообщений: 19,113
14.08.2015, 13:43 12
Цитата Сообщение от VLK Посмотреть сообщение
все закончится печально?
Да.

С другой стороны, возникает два вопроса:
1. Зачем вы лочитесь на проверке i? Она является локальной переменной цикла, не изменяется другими потоками (если где-то за пределами цикла нет захвата), то есть не является общим ресурсом, а значит ей не место в критической зоне.

Вносите в критическую зону только те участки кода, которые непосредственно работают с общими ресурсами:
C#
1
2
3
4
    if (i == 50) break;
    Monitor.Enter(temp);
    temp.Add(temp.Count);
    Monitor.Exit(temp);
2. Зачем вообще проверка на i? Вы на стадии написания кода уже знаете, что цикл идет максимум до i=50, дык сделайте это условием цикла:
C#
1
2
3
4
5
6
for (int i = 0; i < 50; i++)
{
    Monitor.Enter(temp);
    temp.Add(temp.Count);
    Monitor.Exit(temp);
}
1
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
14.08.2015, 13:43

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Доступ к функции с разных потоков C++ Builder
Как правильно объявить/создать функцию в C++Builder, чтобы она была доступна со всех потоков,...

Обеспечить корректный доступ к элементу из разных потоков
Возникла такая проблема. Есть приложение и в приложение есть элемент, к которому прикреплён некий...

Доступ к файлам из разных потоков, как исключить коллизии?
Разные потоки осуществляют чтение разных файлов произвольным образом командой...

Выполнение потоков по очереди
Здравствуйте, изучаю книгу Шилдта и возник вопрос в многопоточности, а именно этот пример: package...


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

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

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