Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.76/29: Рейтинг темы: голосов - 29, средняя оценка - 4.76
12 / 12 / 1
Регистрация: 05.04.2012
Сообщений: 127
1

Синхронизация потоков: проблема гонки потоков

20.10.2014, 03:58. Показов 5367. Ответов 7
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Есть проблема в синхронизации потоков, которую я не знаю, как решить. Точнее у меня получается типичная гонка потоков.
Есть функция, которая меняет статический массив. Если два массива (а и б) равны, то поток завершает выполнение.
Вот сам код функции:
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
static void func(double[] arr)
        {
            Random rd = new Random();
            bool fl = true;
            while (fl)
            {
                
                //Случайно выбираем элемент массива
                int index = rd.Next(0, arr.Length);
                //Если 0, то мы обнуляем элемент, если 1, то умножаем на произвольное число от 1 до 10.
                int flag = rd.Next(0, 1);
                int number = rd.Next(1, 10);
                arr[index] = (flag == 0) ? 0 : arr[index] * number;
                lock (locker)
                {
                    if (Sum(a) == Sum(b)) fl = false;
                }
            }
            
        }

В чем казус? Когда один поток находится в лок, а другой в самом начале функции, первый успевает завершить действие (выходит из цикла), а второй в этот момент меняет значение, и получается условие не равно, и все...Как решить данную проблему, кто подскажет?
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
20.10.2014, 03:58
Ответы с готовыми решениями:

Синхронизация потоков на элементарном уровне (переключение потоков)
в общем разбираюсь с потоками, на сколько понял мне нужен lock Вот имеется просто пример ...

Синхронизация потоков
Есть программа: using System; using System.Diagnostics; using System.Linq; using...

Синхронизация потоков
Здравствуйте! Я понимаю, что подобные вопросы уже много раз задавались, но перечитав подобные темы...

Синхронизация потоков с#
Здравствуйте. Задача у меня такая: нужно, чтобы три потока асинхронно брали из List слова и...

7
Эксперт .NET
5545 / 4308 / 1218
Регистрация: 12.10.2013
Сообщений: 12,356
Записей в блоге: 2
20.10.2014, 05:36 2
Цитата Сообщение от MoonGuard Посмотреть сообщение
Как решить данную проблему
MoonGuard, у вас общий (разделяемый между потоками) ресурс это массив, так? Так почему вы тогда блокируете только небольшой участок кода, а не полностью все операции с общим ресурсом внутри потока? Заблокируйте полностью, ну или используйте потокобезопасные коллекции...
1
12 / 12 / 1
Регистрация: 05.04.2012
Сообщений: 127
20.10.2014, 10:22  [ТС] 3
insite2012, хм, просто если я заблокирую всю функцию, т.е. поставлю её в лок. Тогда в чем соль? Потоки будут выполняться по очереди, ну или кто первый захватит, т.е. потеряю всю параллельность.
Соль такая: у меня есть два массива статических. Один поток работает с одним массивом, другой с другим. В тот момент, когда сумма этих массивов равна, работу надо прекращать. Т.е. общий элемент между потоками - это сравнение вот этих массивов. Получается по логике, надо как-то после каждого изменения в массиве, не важно в каком, вызывать эту функцию, при этом останавливая выполнения всех потоков и возможность прерывания их работы. Единственное, что пришло в голову, это тот код что выше, но моя логика либо неправильна, либо неполна, т.к. возникает вот такой казус не разрешенный. Может вы что подскажите?
0
814 / 422 / 169
Регистрация: 08.02.2013
Сообщений: 711
20.10.2014, 10:57 4
MoonGuard, а если так?: каждый поток работает с копией своего массива, вычисляется сумма элементов, общие ресурсы это оригиналы массивов и суммы, лочится процесс сохранения новой суммы и подмены оригинала массива копией. Если после обработки копии старые суммы совпадают то завершаем поток без подмены массива.
1
325 / 136 / 28
Регистрация: 18.09.2014
Сообщений: 167
20.10.2014, 11:09 5
Лучший ответ Сообщение было отмечено MoonGuard как решение

Решение

Всё-таки придется вносить операцию изменения элемента массива в lock. Несмотря на то, что массивы разные, операция изменения элемента и последующего сравнения должна быть атомарной, т.е. в момент сравнения не должны происходить модификации массивов другими потоками.

Кроме этого, надо гарантировать, что после достижения равенства ни один из потоков больше не будет модифицировать массивы.

Итого вырисовывается след. решение:

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
private static bool _isEqual = false;
static void func(double[] arr)
        {
            Random rd = new Random();
            bool fl = true;
            while (!_isEqual )
            {
                
                //Случайно выбираем элемент массива
                int index = rd.Next(0, arr.Length);
                //Если 0, то мы обнуляем элемент, если 1, то умножаем на произвольное число от 1 до 10.
                int flag = rd.Next(0, 1);
                int number = rd.Next(1, 10);
 
                lock (locker)
                {
                    if(!_isEqual)
                    {
                       arr[index] = (flag == 0) ? 0 : arr[index] * number;
                       if (Sum(a) == Sum(b)) _isEqual = true;
                    }
                }
            }      
        }
1
Эксперт .NET
5545 / 4308 / 1218
Регистрация: 12.10.2013
Сообщений: 12,356
Записей в блоге: 2
20.10.2014, 11:15 6
Цитата Сообщение от MoonGuard Посмотреть сообщение
Может вы что подскажите?
Тогда, если я верно понял, вам действительно нужна синхронизация. Попробуйте использовать для этого класс EventWaitHandler.
1
Эксперт .NET
17791 / 12942 / 3381
Регистрация: 17.09.2011
Сообщений: 21,215
20.10.2014, 11:20 7
Цитата Сообщение от MoonGuard Посмотреть сообщение
C#
1
int flag = rd.Next(0, 1);
Не по теме, но оно же всегда 0 будет, не?
1
12 / 12 / 1
Регистрация: 05.04.2012
Сообщений: 127
20.10.2014, 13:35  [ТС] 8
kolorotur, да вы правы. Я совершенно забыл, что там max-1 значение будет. Просто для повышения вероятности стояло 3 и тесты ошибок не выдавали. После исправил, и забыл про сей важный факт.
Думаю проблему можно считать решенный, всем спасибо
0
20.10.2014, 13:35
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
20.10.2014, 13:35
Помогаю со студенческими работами здесь

Синхронизация потоков c#
Задача о парикмахере. В городе есть салон-парикмахерская, в которой работает только один...

Синхронизация потоков
Есть ли возможность в C# сделать часть кода потока защищенным от прерывания другими потоками. Lock...

Синхронизация потоков
Здравствуйте! Есть задача создать два потока в каждом из которых будет бегущая строка(одна справа...

Синхронизация потоков
Не так давно начал заниматься c#.. возникла следующее недопонимание потоков. Программа ищет в цикле...


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

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru