2010-04-02 12 views
6

Mój program ma dwa wątki:Jak mogę zsynchronizować dostęp do bazy danych między wątkiem do zapisu a wątkiem wczytywanym?

  1. głównym wątku wykonania, który obsługuje dane wejściowe użytkownika i kolejki się baza pisze
  2. Wątek narzędziowy, który budzi się w każdej sekundzie i opróżnia zapisuje do bazy

Wewnątrz wątku głównego czasami potrzebuję odczytów w bazie danych. Kiedy tak się dzieje, wydajność nie jest ważna, ale poprawność jest. (W idealnym świecie chciałbym czytać z pamięci podręcznej, nie robiąc w obie strony bazy danych - ale odłóżmy to na bok w celu dyskusji.)

Jak mogę się upewnić, że główny wątek widzi poprawna/nieaktywna baza danych?

Standardowy muteks nie zadziała, ponieważ istnieje ryzyko, że główny wątek złapie muteks zanim dane zostaną przepuszczone do bazy danych. To byłby wielki wyścig.

To, czego naprawdę chcę, to jakiś muteks, który pozwala, aby główny wątek wykonania działał tylko PO MOCZU, który został raz pobrany i zwolniony. Czy coś takiego istnieje? Jaki jest najlepszy sposób na rozwiązanie tego problemu?

AKTUALIZACJA: Po wykonaniu dodatkowych badań, mogę użyć Boost's Conditional Variable, aby rozwiązać ten problem. Albo to, albo po prostu ugryź kulę i przechowuj w pamięci moje zapiski. Dzięki za opinie!

Odpowiedz

1

Jeśli nie masz więcej niż jednego wątku głównego wykonywania (tzn. Jedynym wątkiem, który będzie naciskał zapisy na wątek roboczy, jest ten sam wątek, który będzie czytał z bazy danych), prawdopodobnie możesz po prostu mieć prosta "oczekująca zapisana" zmienna/funkcja, którą możesz sprawdzić przed wysłaniem odczytać, i zakręcić blokadą lub poczekać na sygnał, aż zapisy zostaną przepłukane. Wygląda na to, że nie trzeba wykonywać żadnych blokad ani synchronizacji w zapisach, jeśli można je po prostu umieścić w kolejce do przetworzenia przez wątek roboczy.

Zasadniczo, dopóki masz gwarancję, że pomiędzy czekiem dla stanu "oczekuje na zapis" i kiedy faktycznie wykonujesz odczyt, nie ma żadnych zapisów, to nie musisz robić nic zbyt wymyślnego.

3

Twoje proponowane rozwiązanie z pewnością nadal powoduje stan wyścigu, ponieważ "zapis" może pojawić się w dowolnym momencie, nawet w połowie nowego zdarzenia, które czeka w kolejce.

Rozwiązaniem, które możesz wypróbować, jest wartość stanu bazy danych atomowych: wykonujesz przetwarzanie, a następnie porównujesz z wartością stanu atomowego, aby upewnić się, że czytasz z bazy danych znajdującej się w stanie, który jest taki sam, jak od momentu rozpoczęcia odczytu . Jeśli jest inaczej, zaczynasz od nowa. Może to być uzależnione od głodu, ale jest to osobny problem.

Przy każdorazowej zmianie bazy danych należy porównać i zamienić wartość stanu atomowego, która była używana, wskazując zmianę.

3

Kilka rozwiązania są możliwe:

  • Czy każdy wątek otworzyć własną d/b połączenia i używać go wyłącznie
  • Za pomocą jednego połączenia, ale mieć każdy wątek właścicielem mutex do niego dostęp.

Nie widzę problemu z drugim wyborem. Jaka jest szkodliwość spłukiwania, gdy nie ma nic do spłukiwania?

+0

Nie jestem pewien, czy to zadziała. Jeśli każdy wątek ma własne połączenie db, może nadal uzyskać dostęp do tej samej tabeli w bazie danych. Nic nie chroni pierwszego wątku przed dostępem do starych danych, które nie zostały jeszcze zaktualizowane przez drugi wątek. – Runcible

+0

Dostęp do jednoczesnego pisania, a także czytania i pisania jest standardową funkcją menedżerów baz danych. Ponieważ pytanie jest oznaczone mysql, nie powinno być problemu. – wallyk

+0

Powiedzmy, że wątek 1 powoduje wstawienie INSERT do tabeli Foo. Następnie - zanim wątek 2 się obudzi i opróżni zapis do bazy danych - wątek 1 wykonuje instrukcję SELECT na tabeli Foo. Nie ma rywalizacji o dostęp, ale wątek 1 wciąż czyta nieaktualne dane. – Runcible

Powiązane problemy