Как я могу синхронизировать доступ к базе данных между потоком записи и потоком чтения? - PullRequest
6 голосов
/ 03 апреля 2010

Моя программа имеет две темы:

  1. Основной поток выполнения, который обрабатывает ввод пользователя и ставит в очередь записи в базу данных
  2. служебный поток, который просыпается каждую секунду и сбрасывает записи в базу данных

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

Как мне убедиться, что основной поток видит правильную / неактивную базу данных?

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

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

ОБНОВЛЕНИЕ: После некоторых дополнительных исследований я мог бы использовать Условная переменная Boost для решения этой проблемы. Либо так, либо просто прикуси пулю и кешируй мои записи. Спасибо за отзыв!

Ответы [ 3 ]

3 голосов
/ 03 апреля 2010

Возможны несколько решений:

  • Пусть каждый поток открывает свое собственное соединение d / b и использует его исключительно
  • Используйте одно соединение, но каждый поток должен иметь мьютекс для доступа к нему.

Я не вижу проблемы со вторым выбором. Какой вред от промывки, когда нечего промывать?

3 голосов
/ 03 апреля 2010

Предложенное вами решение, безусловно, по-прежнему приводит к состоянию гонки, поскольку «запись» может появиться в любое время, даже на полпути через новое событие, находящееся в очереди.

Решение, которое вы можете попробовать, - это атомарное значение состояния базы данных: вы выполняете свою обработку, а затем сравниваете с атомарным значением состояния, чтобы убедиться, что вы читаете из базы данных, которая находится в состоянии, которое совпадает с моментом начала чтения. Если это не так, вы начинаете все сначала. Это может быть связано с голодом, но это отдельная проблема.

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

1 голос
/ 03 апреля 2010

Если у вас нет более одного основного потока выполнения (т. Е. Единственный поток, который будет толкать записи в рабочий поток, - это тот же поток, который будет читать из базы данных), тогда вы, вероятно, можете просто Переменная / функция «ожидающие записи», которую вы можете проверить перед отправкой read , а также выполнить спин-блокировку или дождаться сигнала, пока записи не будут сброшены. Похоже, вам не нужно будет выполнять какую-либо блокировку или синхронизацию для записей, если они могут быть просто поставлены в очередь для обработки рабочим потоком.

В основном, если вам гарантировано, что между проверкой состояния «ожидающие записи» и тем, когда вы фактически выполняете чтение, записи не происходит, тогда вам не нужно делать что-то слишком причудливое.

...