powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Реализация блокирующей очереди на SemaphoreSlim, без lock
14 сообщений из 14, страница 1 из 1
Реализация блокирующей очереди на SemaphoreSlim, без lock
    #39933758
cppc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Блокирующая кольцевая очередь. Будет ли правильно работать такой код? Нужен ли здесь Volatile.Read, Volatile.Write?
Идея такая. Два SemaphoreSlim не дают одновременно писать и читать один и тот же элемент массива. Один семафор - количество элементов, которые точно можно читать (их запись завершена), другой - свободных элементов массива (чтение которых завершилось или они не были записаны). Таким образом, когда хвост доходит до головы или наоборот происходит блокировка.
Вроде как, все нужные барьеры памяти тут есть. Своевременное обновление значения для каждого потока (кэш ядер) обеспечивают Volatile.Read, Volatile.Write. Или тут можно без них? Или для массивов это работать не будет так?
Псевдокод:
Код: 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.
{
        T[] buf = new T[BUFSIZE];
        int start = 0;
        int end = 0;
        SemaphoreSlim canReadCountSemaphoreSlim = new SemaphoreSlim(0);
        SemaphoreSlim canWriteCountSemaphoreSlim = new SemaphoreSlim(BUFSIZE);
        
        public T Dequeue()
        {            
            canReadCountSemaphoreSlim.Wait(); 
            
            int i = Interlocked.Decrement(ref end);
            T val = Volatile.Read(ref buf[i]);                        
            
            canWriteCountSemaphoreSlim.Release();            
            return val;            
        }        
        public void Enqueue(T val)        
        {                        
            canWriteCountSemaphoreSlim.Wait();
            
            int i = Interlocked.Decrement(ref start);
            Volatile.Write(ref buf[i], val);
                        
            canReadCountSemaphoreSlim.Release();            
        }
}



Полный код:
Код: 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.
using System.Threading;
namespace Program
{
    public class BlockingRingQueue<T> where T: class
    {
        const int BUFSIZE_LOG2 = 10;
        const int BUFSIZE = 1 << BUFSIZE_LOG2;
        
        T[] buf = new T[BUFSIZE];
        int start = 0;
        int end = 0;
        SemaphoreSlim canReadCountSemaphoreSlim = new SemaphoreSlim(0);
        SemaphoreSlim canWriteCountSemaphoreSlim = new SemaphoreSlim(BUFSIZE);
        
        public T Dequeue()
        {            
            canReadCountSemaphoreSlim.Wait();
            
            int i = Interlocked.Decrement(ref end);
            i = PositiveMod(i, BUFSIZE);
            T val = Volatile.Read(ref buf[i]);
                        
            canWriteCountSemaphoreSlim.Release();            
            return val;            
        }
        
        public void Enqueue(T val)        
        {                        
            canWriteCountSemaphoreSlim.Wait();
            
            int i = Interlocked.Decrement(ref start);
            i = PositiveMod(i, BUFSIZE);
            Volatile.Write(ref buf[i], val);
                        
            canReadCountSemaphoreSlim.Release();            
        }
        
        static int PositiveMod(int a, int b) => ((a % b) + b) % b;
    } 
}
...
Рейтинг: 0 / 0
Реализация блокирующей очереди на SemaphoreSlim, без lock
    #39933785
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cppc,

1. Задачу озвучьте, что вы таким образом хотите решить?
2. Напишите юнит-тест, какой результат ожидается.

Пока я вижу, что написана какая-то фигня, которая вообще непонятно что делает.
...
Рейтинг: 0 / 0
Реализация блокирующей очереди на SemaphoreSlim, без lock
    #39933872
cppc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
hVostt,

Задача: читать файл по частям, каждую часть обрабатывать в отдельном потоке, результат записывать в файл. При этом использовать async/await, ThreadPool, и т.д. Для этого я собираюсь читать файл по частям каждую часть писать в блокирующую очередь (блокируется когда пуста или переполнена). В отдельных потоках читать из этой очереди, результат писать во вторую такую же очередь. В отдельном потоке читать из второй очереди результаты и писать в файл.
Для этого мне и нужна эта очередь у неё 2 открытых метода
void Enqueue(T val) - добавить в очередь (блокируется, если очередь переполнена пока не будет место)
T Dequeue() - извлечь из очереди (блокируется, если пуста пока не появится элемент)

Я реализовал её без использования lock. Но, не уверен корректно ли она будет работать. В этом и вопрос. Насколько это эффективнее чем lock?
...
Рейтинг: 0 / 0
Реализация блокирующей очереди на SemaphoreSlim, без lock
    #39933966
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cppc,

это проще делается, вам не нужно городить свой велосипед с локами.
если нужен async/await, вам подойдут следующие решения:

1. Channels
2. TPL DataFlow

1-ое простое как тапки.
2-ое позволяет строить сложные цепочки обработки данных.

по сути, вы запускаете 2 потока.
один поток пишет, второй читает.

код тривиальный, попробуйте сами разобраться. будут сложности пишите.
а свой велосипед выкинье )
...
Рейтинг: 0 / 0
Реализация блокирующей очереди на SemaphoreSlim, без lock
    #39933967
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cppc,

повторюсь. никакие локи и семафоры вам не нужны.
...
Рейтинг: 0 / 0
Реализация блокирующей очереди на SemaphoreSlim, без lock
    #39933999
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Уже есть многопоточная очередь ConcurrentQueue<T> , самодельный велосипед вряд ли будет быстрее.
...
Рейтинг: 0 / 0
Реализация блокирующей очереди на SemaphoreSlim, без lock
    #39934062
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T
Уже есть многопоточная очередь ConcurrentQueue<T> , самодельный велосипед вряд ли будет быстрее.


Нет. сорян. Он не поддерживает async/await.
...
Рейтинг: 0 / 0
Реализация блокирующей очереди на SemaphoreSlim, без lock
    #39934069
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
Dima T
Уже есть многопоточная очередь ConcurrentQueue<T> , самодельный велосипед вряд ли будет быстрее.


Нет. сорян. Он не поддерживает async/await.

Код ТСа тоже не поддерживает 22092040
...
Рейтинг: 0 / 0
Реализация блокирующей очереди на SemaphoreSlim, без lock
    #39934152
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T
Код ТСа тоже не поддерживает 22092040


Код ТС вообще дичь )
...
Рейтинг: 0 / 0
Реализация блокирующей очереди на SemaphoreSlim, без lock
    #39934379
cppc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
hVostt,

Задание на многопоточные примитивы библиотечными очередями пользоваться нельзя. Так кончено бы все сделал просто без велосипедов.
...
Рейтинг: 0 / 0
Реализация блокирующей очереди на SemaphoreSlim, без lock
    #39934475
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cppc
hVostt,

Задание на многопоточные примитивы библиотечными очередями пользоваться нельзя. Так кончено бы все сделал просто без велосипедов.

какой хитрый умный перец выдумал такую задачу?
...
Рейтинг: 0 / 0
Реализация блокирующей очереди на SemaphoreSlim, без lock
    #39934866
love_bach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Это задание по своей сути не для C#. Препод копипастил задания
...
Рейтинг: 0 / 0
Реализация блокирующей очереди на SemaphoreSlim, без lock
    #39934870
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ИМХО тут нет самого задания, а только изложение того как ТС понял задание, подозреваю что понял он его неправильно.
...
Рейтинг: 0 / 0
Реализация блокирующей очереди на SemaphoreSlim, без lock
    #39934973
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cppc
hVostt,

Задание на многопоточные примитивы библиотечными очередями пользоваться нельзя. Так кончено бы все сделал просто без велосипедов.


Ну ок. Напишите сначала контракт в виде интерфейса или класса без реализации. Затем юнит-тесты для них. Затем можно приступить к реализации на примитивах.
...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Реализация блокирующей очереди на SemaphoreSlim, без lock
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]