Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
2 / 2 / 2
Регистрация: 18.07.2013
Сообщений: 124
.NET 4.x

Lock должен блокировать при заполнении - чтение и заполнение, а при чтении ничего

12.06.2018, 02:16. Показов 1191. Ответов 6
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток, проблема с блокировкой потоков lock.
1й поток в цикле заполняет коллекцию и 3 потока читают, необходимо блокировать 2й, 3й и 4й поток, когда 1 поток добавляет элемент, но в то же время не нужно блокировать потоки при чтении, допустим 3 потока могут читать без блокировок. Проблема в том, что если везде указать lock, то и при чтении будут блокировки, что негативно сказывается на производительности =(
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
12.06.2018, 02:16
Ответы с готовыми решениями:

Программа вылетает с ошибкой нарушения прав доступа при чтении при заполнении дерева более чем 50 элементами
Приветствую всех. Задание: Для древовидных структур данных предусмотреть вывод характеристик сбалансированности дерева (средняя длина...

При заполнении Edit-а в файл ничего не записывается
Здравствуйте нуждаюсь в помощи.При заполнении едита в файл ничего не сохраняется.в чем может быть ошибка? ...

Автоматическое заполнение данных в поле таблицы при заполнении формы по связанной таблице
Добрый день! Прошу помощи: сама в Access на уровне пользователя, но жизнь заставила.. Суть проблемы: надо прописать обработку, чтобы...

6
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
12.06.2018, 04:05
KinDer015, посмотрите в сторону использования вот этого класса для блокировки.
1
2 / 2 / 2
Регистрация: 18.07.2013
Сообщений: 124
12.06.2018, 04:28  [ТС]
Спасибо за совет, завтра протестирую
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
12.06.2018, 08:53
Цитата Сообщение от KinDer015 Посмотреть сообщение
но в то же время не нужно блокировать потоки при чтении
Смотря что за коллекция.
Некоторые — очень даже нужно блокировать при чтении.
0
2 / 2 / 2
Регистрация: 18.07.2013
Сообщений: 124
12.06.2018, 20:08  [ТС]
SortedDictionary в нем 200к значений, для теста в реальности будет 10-15к (для бинарного поиска по скорости практически не отличается от 200к), мне необходимо изменять около 400 тыс. значений по ключу в сек. и одновременно делать выборку по ключу 600 тыс. раз в секунду (и всего лишь 100-200 добавлений в сек.)

Пытаюсь добиться этой производительности на четырехъядерном процессоре xeon x3440 с помощью многопоточности. (на данный момент лучшая производительность на 16 потоках)

Добавив cacheLock.EnterWriteLock(); в цикл с добавлением новых значений, удалось избавится от краша приложения, за 0,85 сек. потоки читают 600к/сек. и изменяют 400к/сек., по скорости работы на мой взгляд даже очень не плохо, в 3 раза быстрее чем с lock, но немного смущает тот факт, что после 10-30 повторений multithreadSortDic() выводит в консоль "Not found" 1 или 2 раза. Если поставить блокировки везде, то скорость упадет в 3 раза. Может быть просто костыльным методом повторять поиск, если выбило "Not found"? xD Или есть другие способы? (еще не пробовал пул потоков)

немного *овнокода xD
Кликните здесь для просмотра всего текста
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
SortedDictionary<string, string> SortedDic = new SortedDictionary<string, string>();
private ReaderWriterLockSlim cacheLock = new ReaderWriterLockSlim();
 
private void multithreadSortDic()
        {
            SortedDic.Clear();
            int threadWait = 0;
            bool threadWork = false;
            string t;
            for (int i = 0; i < 200000; i++) 
            {
                t = i.ToString();
                if (!SortedDic.ContainsKey(t))
                {
                    SortedDic.Add(t, t);
                }
            }
 
            Thread[] threads1 = new Thread[8]; // потоки для изменения значений по ключам
            for (int i = 0; i < threads1.Length; i++)
            {
                int threadId = i;
                Thread.Sleep(3);
                threads1[i] = new Thread(delegate ()
                {
                    while (!threadWork) { Thread.Sleep(10); } // ожидание команды для работы потоков
 
                    int iterCount = (400000 / threads1.Count()); // при любом числе потоков кол-во итераций в сумме будет равным 400к
                    int count = 0;
 
                    for (int k = 0; k < iterCount; k++)
                    {
                        string c = count.ToString();
                        if (count >= 99999) { count = 0; }
                        count++;
 
                        SortedDic[c] = "t" + c;
                    }
 
                    threadWait++;
 
                });
                threads1[i].Start();
            }
 
            Thread[] threads2 = new Thread[8]; // потоки для чтения значений по ключам
            for (int i = 0; i < threads2.Length; i++)
            {
 
                int threadId = i;
                Thread.Sleep(3);
                threads2[i] = new Thread(delegate ()
                {
                    while (!threadWork) { Thread.Sleep(10); } // ожидание команды для работы потоков
 
                    float iterCount = (600000 / threads2.Count()); // при любом числе потоков кол-во итераций в сумме будет равным 600к
                    int count = 0;
 
 
                    string result;
                    for (int k = 0; k < iterCount; k++)
                    {
                        if (count >= 99999)
                        {
                            count = 0;
                        }
                        count++;
 
                        if (SortedDic.TryGetValue(count.ToString(), out result))
                        {
 
                        }
                        else
                        {
                            Console.WriteLine("Not found: " + count.ToString());
                        }
 
                    }
 
                    threadWait++;
 
                });
                threads2[i].Start();
            }
 
 
            Thread.Sleep(1000); // ожидание для инициализации потоков
            Console.WriteLine("done");
 
            timerStart(); // запускаем таймер
            threadWork = true; // разрешаем потокам начать работу
 
 
            cacheLock.EnterWriteLock();
            for (int i = 0; i < 50000; i++)  // добавляем 50000 записей, чисто ради теста, в реальности будет 100-200 в секунду
            {
                t = i.ToString();
                SortedDic["y" + t] = t;
               
            }
            cacheLock.ExitWriteLock();
 
 
            while (threadWait < (threads1.Count() + threads2.Count())) { Thread.Sleep(10); } // ожидаем пока потоки выполнят свои циклы записи и чтения
 
            timerStop(1); // останавливаем таймер
            Console.WriteLine(SortedDic.Count);
 
            foreach (var thread in threads1) // убиваем потоки записи
            {
                thread.Abort(); 
            }
            foreach (var thread in threads2) // убиваем потоки чтения
            {
                thread.Abort();
            }
            multithreadSortDic(); // для длительного тестирования запускаем повторно
        }


Добавлено через 7 минут
Еще есть предположение, что если заблокировать не только запись для других потоков но и чтение в момент добавления, то данная проблема исчезнет, но в этом случае выбивает исключение.

C#
1
2
3
4
5
6
7
8
9
10
 
            cacheLock.EnterReadLock();
            cacheLock.EnterWriteLock();
            for (int i = 0; i < 50000; i++)  
            {
                t = i.ToString();
                SortedDic["y" + t] = t;            
            }
            cacheLock.ExitReadLock();
            cacheLock.ExitWriteLock();
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
12.06.2018, 20:14
Цитата Сообщение от KinDer015 Посмотреть сообщение
Добавив cacheLock.EnterWriteLock(); в цикл с добавлением новых значений
А где же синхронизация в потоках?

Цитата Сообщение от KinDer015 Посмотреть сообщение
Еще есть предположение, что если заблокировать не только запись для других потоков но и чтение в момент добавления
Почитайте документацию к этому классу — что конкретно могут делать потоки при каком замыкании.
Сразу поймете, почему выбивает.
0
2 / 2 / 2
Регистрация: 18.07.2013
Сообщений: 124
13.06.2018, 08:44  [ТС]
В общем я бегло посмотрел документацию, сейчас внимательно прочитаю, не совсем понял, что подразумевается под синхронизацией в потоках

Добавлено через 6 часов 35 минут
Добавил блокировку через отдельную функцию, как в документации, которая дает доступ только одному потоку, а чтение разрешает всем. Все работает как нужно без исключений, но к сожалению время возросло до 2 сек. Разбивать коллекцию на равные части для потоков не даст большей производительности, так как у нас бинарный поиск. В итоге данное приложение должно быть заточено под 12-и ядерный сервер, где довольно низкая производительность на ядро. Как я понимаю бинарный поиск на такой машине будет проигрывать некоторым другим методам сортировки и выборки, которые подойдут для многопоточности, но вот какие стоит использовать не знаю.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
13.06.2018, 08:44
Помогаю со студенческими работами здесь

Ошибка при чтении файла: Чтение после конца потока невозможно
Всем добрый вечер! Пытаюсь считать данные из rtf файла и загрузить их в excel файл. Но выпадает exception: Чтение после конца потока...

"Нарушение прав доступа при чтении по адресу" при чтении структур из бинарного файла
Пытаюсь разобраться со структурами в бинарных файлах. Допустим, есть массив структур. Записываю его в бинарный файл (закомментированный...

При чтении dll библиотеки в обычном(не бинарном) виде, чтение прерывается на NULL
Задача такая: открыть dll файл(не мой) в обычном текстовом виде(каким его могут открыть обычные блокноты), найти нужную последовательность...

При нажатии на клавиши Num Lock, Caps Lock, Insert вывести в StatusBar состояние кнопок C++
Добрый день, уважаемые программисты, студенты, школьники, а также все посетители этого замечательного форума. помогите, пожалуйста,...


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

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru