Наилучший подход к синхронизации свойств между потоками

#c #multithreading

#c #многопоточность

Вопрос:

Я ищу несколько советов о наилучшем подходе к синхронизации доступа к свойствам объекта в C . Приложение имеет внутренний кэш объектов, которые имеют 10 свойств. Эти объекты должны запрашиваться в наборах, свойства которых затем могут быть изменены и повторно сохранены. К ним могут быть доступны 2-4 потока в любой момент времени, но доступ не интенсивный, поэтому мои варианты:

  1. Заблокируйте средства доступа к свойствам для каждого объекта, используя критическую секцию. Это означает множество критических разделов — по одному для каждого объекта.

  2. Возвращает копии объектов по запросу и имеет функцию обновления, которая блокирует один критический раздел для обновления свойств объекта при необходимости.

Я думаю, что вариант 2 кажется наиболее эффективным, но я просто хочу посмотреть, не упускаю ли я скрытый третий вариант, который был бы более подходящим.

Спасибо, J

Комментарии:

1. это не похоже на общепринятое значение термина «кэш»; пожалуйста, поясните

2. Что происходит в случае обновления, если объект изменился? Вы думаете о каком-нибудь CAS?

3. Извините, что это кэш, я просто имею в виду, что объекты предварительно загружены в память, а не должны быть прочитаны с диска. Это в значительной степени не имеет отношения к вопросу, поэтому, пожалуйста, извините за неправильную формулировку.

4. В случае изменения объекта мы проверяем, изменился ли он, и действуем соответствующим образом.

Ответ №1:

Во-первых, я думаю, вы беспокоитесь не о том. Откуда вы знаете, что блокировка или копирование вызывает узкие места в вашем коде? Критические разделы довольно легкие и не вызывают больших накладных расходов или, по крайней мере, не так сильно, как вы думаете. Просто используйте самый легкий доступный примитив блокировки. Если вы предполагаете, что ваша система будет работать на многопроцессорном оборудовании, вы можете даже использовать блокировку вращения.

Во-вторых, побеспокойтесь о простоте вашей модели параллелизма, а не о производительности (подсказка: более простую модель легче понять, настроить правильно и оптимизировать). Поэтому, если вы можете себе это позволить, делайте копии объектов, это облегчит работу с условиями гонки TOCTOU в случае, если вы выполняете сложные преобразования в наборе объектов, которые зависят от ряда предыдущих значений.

Ответ №2:

Вам не нужны критические разделы, вам нужен мьютекс.

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

Мьютексы имеют довольно низкие накладные расходы, когда нет конфликта. Когда возникает много конфликтов, они определенно могут замедлить работу вашей программы.

Комментарии:

1. Почему мьютекс, а не критический раздел?

2. таким образом, 2 разных потока не смогут обновить 2 разных свойства одного и того же объекта.

3. Ошибка… вам нужен мьютекс, который определенно может замедлить работу вашей программы? @Nick D: Какой это способ?

4. @AOI Karasu, используя мьютекс для блокировки всего объекта.

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

Ответ №3:

В зависимости от того, сколько времени требуется для чтения свойства из объекта (я предполагаю, что это должно быть довольно тривиально, например, чтение int или std::string), вы могли бы использовать спин-блокировки в качестве # 3. Это самый быстрый способ синхронизации потоков. И, возможно, вариант № 4, действительный только для целых чисел, заключается в том, чтобы вообще не выполнять блокировку и использовать только атомарные операции. Возможно, наиболее эффективным решением было бы использование атомаризации для всех целых чисел, спин-блокировок для каждого свойства для простых типов (модулей и простых объектов, таких как std::string) и мьютексов для каждого объекта / CS для чего-либо более сложного.

Только профилировщик сможет сказать вам, какой вариант является наилучшим.