Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.59/29: Рейтинг темы: голосов - 29, средняя оценка - 4.59
22 / 22 / 10
Регистрация: 19.03.2015
Сообщений: 137

Один mutex на несколько функций

19.04.2016, 13:56. Показов 6922. Ответов 50
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Есть три функции, которые могут работать с одним вектором в одно и то же время из разных потоков. Можно ли использовать один мьютекс на эти несколько функций, чтобы не синхронизировать работу 3-х мьютексов?
Код чисто для примера, чтобы было понятно, чего я хочу
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
mutex m;
vector<int> vec;
 
void Add(int i)
{
    m.lock();
        try
        {
            vec.push_back(i);
        }
        catch(exception ex)
        {
            m.unlock();
            throw ex;
        }
    m.unlock(); //все ок.
}
 
void Remove(int i)
{
    m.lock()
        try
        {
            //находим с помощью итераторов индекс с значением i и erasим его
            ...
        }
        catch(exception ex)
        {
            //если произойдет ошибка, анлокним мьютекс, чтобы другие функции могли
            //продолжить работу, а ошибку пробросим выше.
            m.unlock();
            throw ex;
        }
    m.unlock(); //все ок.
}
 
void Read(int index)
{
    m.lock()
        try
        {
            for (int i=0; i<vec.size(); i++)
            {
                if (i==index)
                {
                    vec[i].....
                    //шаманим со значением по индексу...
                }
            }
        }
        catch(exception ex)
        {
            m.unlock();
            throw ex;
        }
    m.unlock(); //все ок.
}
2
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
19.04.2016, 13:56
Ответы с готовыми решениями:

вывод на один график несколько функций
ребят поясните плз! как вывести 2 массива на один график ??? точки каждого желательно разным цветом :) y = wavread('D:\3_3s.wav'); ...

Как записывать несколько одномерных массивов, и несколько двумерных массивов в один единственный текстовый файл
Как записывать несколько одномерных массивов, и несколько двумерных массивов в один единственный текстовый файл? Что-то не видел других...

Несколько функций в IF
День добрый.Есть код: &lt;?php if (mail(&quot;nobody@example.com&quot;, &quot;the subject&quot;, &quot;Example message&quot;, &quot;From: webmaster@example.com...

50
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
20.04.2016, 11:41
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Nosey Посмотреть сообщение
std::begin(vec), std::end(vec)
Моя школа А то все пишут vec.begin()
0
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
20.04.2016, 13:07
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Если несколько потоков конкурируют за один mutex, то порядок их прихода на этот mutex - это просто ярчайший, хрестоматийнейший пример "гонки".
Гонка - это когда мьютекса нет вообще и потоки мешают друг другу.

Если несколько потоков используют мьютекс для доступа к ресурсу, при этом порядок обращения к мьютексу и время удержания произвольные, то где гарантия, что один и тот же поток не будет неограниченно долго удерживать мьютекс просто освобождая и тут же захватывая его повторно, ведь очереди нет, и не гарантируется, что освобождение мьютекса одним поток обязательно активирует ожидающих?
0
22 / 22 / 10
Регистрация: 19.03.2015
Сообщений: 137
20.04.2016, 13:38  [ТС]
Цитата Сообщение от Nosey Посмотреть сообщение
Я ни коем образом не гнул, извиняюсь если так вышло ) Я лишь хотел подсказать куда копать дальше.
Ох, забыл процитировать сообщение. Да не, не Вам это, а TheCalligrapher'у. Ваше сообщение очень кстати.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13205 / 6840 / 1822
Регистрация: 18.10.2014
Сообщений: 17,298
20.04.2016, 20:32
Цитата Сообщение от nmcf Посмотреть сообщение
Гонка - это когда мьютекса нет вообще и потоки мешают друг другу.
Ни в коем случае.

Race condition ("гонка") - это огромный класс семантических проблем, суть которых сводится к тому, что программа пытается завязываться на такие предположения о многопоточном поведении, которые на самом деле является неопределенными (unspecified или undefined). А именно, когда программа пытается делать предположения о существовании некоего детерминированного "порядка" или "скорости" выполнения потоков.

В этом множестве вариантов разнообразных гонок несинхронизированный/неатомарный доступ к кусочку данных - это лишь очень узенький и весьма нерепрезентативный частный пример возможной гонки. Это во-первых. Во-вторых, предположение о том, что "заоболачивание" доступа к данным в mutex как-то решает проблему гонки - наивное заблуждение. Это не говоря уже о том, что приемы синхронизации в многопоточном программировании далеко не сводятся к использованию "классических" примитивов, типа mutex.

Вот вам искусственный пример гонки, причем буквальной: пусть у меня есть глобальная переменная int i = 0 и несколько одинаковых потоков, которые, кроме прочего, делают ++i и запоминают результат. Пусть я запускаю эти потоки поочередно с задержкой Dt по времени между потоками. И я предполагаю, что те потоки, которые стартовали раньше, "доберутся" до ++i тоже раньше. Соответственно, я предполагаю, что первый запущенный поток получит из i значение - 1, второй - 2 и т.д. Пусть я в дальнейшем коде сильно завишу от выполнения этого предположения.

Вот это - яркий пример гонки. Мое предположение - грубейшим образом некорректно. То, что некий поток стартовал позже, никак не мешает ему обогнать более ранний поток в процессе выполнения. При этом заоболачивание доступа к ++i в mutex никак делу не поможет - выполнение моего предположения все равно не гарантируется и оно не будет выполняться. Вот это - классический race condition. Заоболочив доступ к ++i в mutex я лишь перенес точку финиша в этой гонке, но саму гонку и ее негативные последствия никак не устранил.

Нерадивый программист в такой ситуации может начать увеличивать величину задержки Dt, в надежде на то, что для какого-то значения Dt порядок прихода потоков на ++i, наконец, станет совпадать с порядком их запуска. Понятно, что это не более чем профанация.

В такой ситуации, если я действительно хочу, чтобы потоки выполняли ++i в некотором четко определенном мною порядке, я должен буду самостоятельно насильно ловить и задерживать "выбившиеся вперед" потоки. И делать это придется вручную.

Цитата Сообщение от nmcf Посмотреть сообщение
Если несколько потоков используют мьютекс для доступа к ресурсу, при этом порядок обращения к мьютексу и время удержания произвольные, то где гарантия, что один и тот же поток не будет неограниченно долго удерживать мьютекс просто освобождая и тут же захватывая его повторно, ведь очереди нет, и не гарантируется, что освобождение мьютекса одним поток обязательно активирует ожидающих?
Такая гарантия и есть, и нет.

Такая гарантия есть, потому что освобождение и последующий захват одного mutex потоком A - операция неатомарная. В традиционной реализации, если в этот момент какой-то другой поток B ожидал этого же mutex и был в этот момент готов к выполнению, этот поток B тут же захватит этот mutex еще в момент освобождения его потоком A. Как бы быстро A не попытался снова захватить mutex, он все равно "не успеет".

Такой гарантии нет например потому, что ожидающий поток B в момент освобождения mutex может оказаться не готов к выполнению. Например, ОС могла "на секундочку" захватить ресурсы потока B и переиспользовать их для решения каких-то своих внутренних задач (типа обслуживания прерывания неким внутренним системным потоком C). Поток B на это время будет "заморожен". Т.е. может получится так, что поток B "прохлопает" свою возможность захватить mutex, и поток A сможет успеть снова захватить его прямо под носом у потока B.

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

Но опять же, в недискриминирующем отношении ОС к потокам не содержится никаких гарантий порядка выполнения потоков. Если вам нужен порядок - огранизуйте его сами. И многопоточное программирование предполагает дизайн программы по принципу: если что-то очень маловероятно, но теоретически возможно, то оно рано или поздно произойдет.

Добавлено через 10 минут
Цитата Сообщение от Bushmeister Посмотреть сообщение
Ой, вот только не надо тут пальцы гнуть, если ещё кто-то не вникал в тему с мьютексами и знает их поверхностно, без практики. Похоже, придется напомнить, что это раздел для начинающих в C++. Для вас "странные вопросы" - абсолютно нормальные, логичные для тех, кто ещё не работал с этим серьезно и желает получить правильное решение, чтобы потом не наступать на грабли.
Перед вами никто не "гнет пальцы".

Когда некто в форуме "для начинающих математиков" задает вопрос типа "Решал уравнение x + 2 = 4. Получил ответ x=3, но что-то не сходится. Где ошибка?", то на такой вопрос можно дать два принципиально разных ответа. Первый ответ: "Правильное решение x=2. Свободен.". Второй ответ: "Покажи, как ты получил такой странный результат (а мы покажем тебе, где именно ты ошибся в процессе решения)". Я лично считаю, что в такой "странной" ситуации, как "решал x + 2 = 4, получил x=3" первый вариант ответа на самом деле бесполезен, а осмысленен именно и только второй вариант ответа.

Вот так же и здесь, когда я у вас спрашиваю, "откуда возник такой вопрос", цель этого - именно понять, какая цепочка умозаключений привела вас к "странному" выводу, что для трех функций необходимо три мьютекса, и затем уже искать ошибку в этой цепочке. Ни больше, ни меньше.
5
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
20.04.2016, 23:14
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Такая гарантия и есть, и нет.
Ну вот и я о том же.
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
не будут как-то выражено дискриминироваться планировщиком потоков.
Это если они просто выполняются независимо. А если задействован мьютекс, то они сами начинают мешать планировщику.
0
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
20.04.2016, 23:32
Цитата Сообщение от nmcf Посмотреть сообщение
А если задействован мьютекс, то они сами начинают мешать планировщику.
С чего бы вдруг?
0
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
21.04.2016, 10:38
Цитата Сообщение от avgoor Посмотреть сообщение
С чего бы вдруг?
Потому что обращение к мьютексу будет останавливать потоки, и тем самым будет перераспределяться время.
0
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
21.04.2016, 11:48
Цитата Сообщение от nmcf Посмотреть сообщение
Потому что обращение к мьютексу будет останавливать потоки,
А кто будет останавливать потоки при обращении к мьютексу, если не планировщик? А если это не системный мьютекс, а простой спинлок?
0
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
21.04.2016, 11:55
avgoor, дело не в том, что останавливает планировщик, а в том по чьей команде.
0
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
21.04.2016, 12:01
Цитата Сообщение от nmcf Посмотреть сообщение
а в том по чьей команде
Какая разница? Например в винде, если вы в цикле обработки событий вызываете Sleep(0) - вы помогаете планировщику, а не наоборот.
А вообще, планировщик делают с оглядкой на такие вещи.
1
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
21.04.2016, 14:31
Цитата Сообщение от avgoor Посмотреть сообщение
А вообще, планировщик делают с оглядкой на такие вещи.
Ну и почему нет очереди тогда? Логично же передавать управление тому, кто дольше ждёт.
0
27 / 26 / 6
Регистрация: 02.02.2014
Сообщений: 96
21.04.2016, 15:06
Логично потратить как можно меньше времени и разбудить первый попавшийся ждущий поток. Fair синхронизация нужна слишком редко, чтобы ради нее в ядро вкорячивать лишний код, тем более в таком месте.
0
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
21.04.2016, 15:14
Цитата Сообщение от warhast Посмотреть сообщение
потратить как можно меньше времени и разбудить первый попавшийся ждущий поток
Попавшийся где? Они же хранятся в каком-то контейнере, значит очерёдность там - не проблема.
0
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
21.04.2016, 17:06
Цитата Сообщение от nmcf Посмотреть сообщение
Ну и почему нет очереди тогда? Логично же передавать управление тому, кто дольше ждёт.
Цитата Сообщение от nmcf Посмотреть сообщение
Попавшийся где? Они же хранятся в каком-то контейнере, значит очерёдность там - не проблема.
Там есть какая-то очередность, но она, в общем случае, не совпадает с FIFO, потому, что это никому не надо, TheCalligrapher уже объяснил почему. Если вам так нужна эта очередь, организуйте ее самостоятельно. Но учитывайте, что никак невозможно заранее определить порядок в котором потоки в эту очередь попадут.
0
27 / 26 / 6
Регистрация: 02.02.2014
Сообщений: 96
21.04.2016, 17:17
Пример: поток освобождает мьютекс (лежащий за ним футекс) и будит ожидающего. Но в этот момент набегает новый поток и хватает освободившийся футекс. Проснувшийся ожидавший видит, что прощелкал свой шанс и засыпает обратно, причем уже в конце очереди. И вот такое проверять никто не будет без нужды.
0
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
21.04.2016, 17:17
Поясню подробнее. Один поток может 10 раз успеть захватить и освободить мьютекс, пока второй доберется до захвата этого мьютекса, т.е. постановки в очередь.
0
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
21.04.2016, 18:04
Цитата Сообщение от warhast Посмотреть сообщение
поток освобождает мьютекс (лежащий за ним футекс) и будит ожидающего. Но в этот момент набегает новый поток и хватает освободившийся футекс.
Не понял я твой пример. Потоки активируются не сами собой, а извне. Если всё, как ты описал, то как вообще гарантировать хоть какую-то равномерность выполнения?
Цитата Сообщение от avgoor Посмотреть сообщение
Один поток может 10 раз успеть захватить и освободить мьютекс, пока второй доберется до захвата этого мьютекса
Я об этом и говорю. Без очереди будет бардак - одни оттеснят других.
0
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
21.04.2016, 18:23
Цитата Сообщение от nmcf Посмотреть сообщение
Я об этом и говорю. Без очереди будет бардак - одни оттеснят других
1) Мьютекс почти всегда свободен. Потому, что если он почти всегда занят - практически вы имеете однопоточный алгоритм с оверхедом в виде потоков.
2) Если потоки равнозначны (читай делают одно и то же) - какая вам разница, какой поток захватит мьютекс?
3) Если потоки не равнозначны - какая разница, какой из них первым попытался захатить мьютекс, если все равно нужен приоритет?
Исходя из вышесказанного зачем нужна строгая очередность в захвате мьютексов?

Добавлено через 8 минут
Цитата Сообщение от nmcf Посмотреть сообщение
Без очереди будет бардак - одни оттеснят других
Но мьютексы к этому не имеют никакого отношения.
0
27 / 26 / 6
Регистрация: 02.02.2014
Сообщений: 96
21.04.2016, 18:27
О какой именно "равномерности" речь?
0
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
21.04.2016, 18:50
Цитата Сообщение от avgoor Посмотреть сообщение
Мьютекс почти всегда свободен
Откуда это следует? И на сколько он должен быть свободен, чтобы гарантировать захват всеми желающими, на секунду, на минуту?
Цитата Сообщение от avgoor Посмотреть сообщение
Исходя из вышесказанного зачем нужна строгая очередность в захвате мьютексов?
Я уже сказал - в первую очередь, чтобы потоки выполнялись равноправно.

Добавлено через 2 минуты
Цитата Сообщение от warhast Посмотреть сообщение
О какой именно "равномерности" речь?
О равномерном выполнении всех потоков. Чтобы все получали шанс и время, а не находились в состоянии ожидания, пока кто-то вне очереди перехватывает мьютекс.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
21.04.2016, 18:50
Помогаю со студенческими работами здесь

несколько функций
как сделать несколько например OnMauseMuve для компонента???

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

Добавить несколько функций
привет всем) вот есть код на С++ в консольном приложении VS 2008 - калькулятор с функциями сложения, вычитания, умножения и деления....

Несколько функций поток
Доброго времени суток! Пишу файловый менеджер, в нём есть поток, который выполняет несколько функций, а именно копирует, удаляет,...

Несколько примеров функций
1) Приведите пример функции, которая не имеет второй производной в точке х=1, а первая производная в этой точке конечна. 2) Приведите...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
[golang] Алгоритм «Хак Госпера»
alhaos 17.05.2026
Алгоритм «Хак Госпера» Хак Госпера (Gosper's Hack) — алгоритм нахождения следующего по величине числа с тем же количеством установленных бит. Придуман Биллом Госпером в 1970-х, опубликован в. . .
Рисование бинарного древа до 6-го колена на js, svg.
russiannick 17.05.2026
<svg width="335" height="240" viewBox="0 0 335 240" fill="#e5e1bb"> <style> <!]> </ style> <g id="bush"> </ g> </ svg> function fn(){ let rost;/ / высота древа let xx=165,yy=210,w=256;
FSharp: interface of module
DevAlt 16.05.2026
Интерфейс модуля F# позволяет управлять доступностью членов, содержащихся в реализации модуля. По-умолчанию все члены модуля доступны: module Foo let x = 10 let boo () = printfn "boo" . . .
Хитросплетение родственных связей пантеона греческих богов.
russiannick 14.05.2026
Однооконник, позволяющий узреть и изучить отдельных героев древней Греции. <!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible". . .
[golang] Угол между стрелками часов
alhaos 12.05.2026
По заданным значениям часа и минуты необходимо определить значение меньшего угла между стрелками аналогового циферблата часов. import "math" func angleClock(hour int, minutes int) float64 { . . .
Debian 13: Установка Lazarus QT5
ВитГо 09.05.2026
Эта инструкция моя компиляция инструкций volvo https:/ / www. cyberforum. ru/ blogs/ 203668/ 10753. html и его же старой инструкции по установке Lazarus с gtk2. . .
Нейросеть на алгоритме "эстафета хвоста" как перспектива.
Hrethgir 06.05.2026
На десерт, когда запущу сервер. Статья тут https:/ / habr. com/ ru/ articles/ 1030914/ . Автор я сам, нейросеть только помогает в вопросах которые мне не известны - не знаю людей которые знали-бы. . .
Асинхронный приём данных из COM-порта
Argus19 01.05.2026
Асинхронный приём данных из COM-порта Купил на aliexpress термопринтер QR701. Он оказался странным. Поключил к Arduino Nano. Был очень удивлён. Наотрез отказывается печатать русские буквы. Чтобы. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru