Как синхронизировать доступ к индексу массива - PullRequest
1 голос
/ 12 мая 2019

Я пишу две программы, которые имитируют банковскую услугу.Там серверная программа и пользовательская программа.Сервер устанавливает несколько потоков, которые функционируют как «электронные счетчики», которые читают запросы пользователя и делают, как они говорят.

Учетные записи пользователей хранятся на сервере в массиве, и к ним можно получить доступ в зависимости от запросов.Моя проблема заключается в следующем: представьте себе, что поток А переводит деньги от Джона Марии.Как я могу остановить доступ других потоков к учетной записи Джона и Марии во время транзакции?Я знаю о семафорах, мьютексах и условных переменных, но не могу найти способ использовать их так, чтобы не блокировать доступ ко всему массиву.

РЕДАКТИРОВАТЬ: мне сказали создать Nмьютексы, где N = количество учетных записей, и каждый мьютекс связан с учетной записью.Есть ли лучшее решение для решения этой проблемы?

1 Ответ

4 голосов
/ 12 мая 2019

Есть несколько опций, среди которых:

Опция 1

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

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

Опция 2

Свернуть свои собственные блокировки на уровне записи.Установите переменную для каждой записи учетной записи, заблокирована ли эта учетная запись.Это может быть внутри массива учетных записей или в отдельной структуре данных.Используйте один мьютекс для защиты доступа ко всем флагам блокировки и CV, чтобы помочь потокам в ожидании получения блокировки.

Затем потоки работают по следующему шаблону:

  1. Заблокируйте мьютекс.
  2. Если все необходимые записи разблокированы, включите их флаги блокировки и перейдите к шагу 4.
  3. Подождите резюме, затем вернитесь к шагу 2.
  4. Отключение мьютекса
  5. Выполнение всех (других) модификаций учетной записи
  6. Повторная блокировка мьютекса
  7. Отключение всех блокировок записей, полученных вШаг 2.
  8. Трансляция в CV и освобождение мьютекса.

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

...