2011-09-27 6 views
5

Piszę kod w C++. Czy mogę natknąć się na jakiekolwiek warunki wyścigowe lub usterki?Czy wiele wątków może jednocześnie zapisywać do pliku, jeśli wszystkie wątki zapisują się w różnych lokalizacjach?

+2

Jeśli potrzebujesz niesekwencyjnego równoczesnego dostępu do plików, polecam zamiast tego użycie zmapowanego pliku pamięci. Następnie traktuj to jak normalną pamięć i wykonaj własne blokowanie (które nie jest potrzebne, jeśli możesz zagwarantować, że lokalizacje zapisu/odczytu nie nakładają się). –

Odpowiedz

6

Nie ma problemu z robieniem tego z punktu widzenia systemu bazowego (dla wszystkich systemów, które znam). Jednak zazwyczaj musisz mieć całkowicie oddzielne deskryptory plików/uchwyty. Dzieje się tak dlatego, że deskryptor pliku utrzymuje stan, np. aktualna pozycja pliku.

Należy również sprawdzić bezpieczeństwo wątku określonego interfejsu C++ w używanym systemie plików. Jest to potrzebne oprócz bezpieczeństwa wątków podstawowego systemu plików.

Należy również wziąć pod uwagę możliwość spowolnienia wątków we/wy. System może wymagać serializacji dostępu do magistrali. Możesz uzyskać lepszą wydajność od nakładających się we/wy lub dedykowanego wątku we/wy podawanego przez potok producenta/konsumenta.

+0

W każdym z wątków otwieram ten sam plik, a następnie zapisuję w pliku zgodnie z pozycją, która jest inna dla każdego wątku. Tak, mogę iść do przodu i wdrożyć prawo ??? – Invictus

+0

Nie mogłem powiedzieć na pewno. Nie pokazałeś swojego kodu. Ale dopóki masz różne uchwyty, powinieneś być w porządku. –

1

Pewnie, że możesz. Warunki wyścigu mogą występować w zależności od tego, jak piszesz aktualny kod (np. Używając tego pliku). Ponadto, jeśli IO jest buforowane, mogą się pojawić dziwne rzeczy, jeśli buforowane regiony się pokrywają.

2

To zależy. Pliki nie są ich uchwytami, a strumienie nie są plikami. Te trzy różne koncepcje muszą być jasne.

System operacyjny może teraz otwierać plik więcej razy, zwracając różne uchwyty, z których każdy ma własny "wskaźnik pozycji". Jeśli plik jest otwarty w "trybie udostępniania" zarówno do odczytu, jak i zapisu, możesz wyszukiwać uchwyty tam, gdzie chcesz i czytać/pisać, jak chcesz. Fakt, że nie nadpisujesz, zależy od Ciebie. System przyznaje sekwencyjność operacji dla całego pliku lub jego części (ale wymagane są dodatkowe informacje o systemie operacyjnym)

Jeśli każdy uchwyt jest podłączony do innego strumienia, każdy strumień będzie zapisywać niezależnie od inny. Ale w tym przypadku występuje komplikacja polegająca na "buforowaniu" (pisanie może być opóźnione, a odczyt można przewidzieć: może być dłuższy, niż ten, o który pytasz: upewnij się, że prawidłowo pokrywasz się przez odpowiednie przepłukanie)

+0

W każdym z wątków otwieram ten sam plik, a następnie zapisuję w pliku zgodnie z pozycją, która jest inna dla każdego wątku. Tak, mogę iść do przodu i wdrożyć prawo ??? – Invictus

+0

@Invictus: Musisz otworzyć plik do udostępnienia. Wszystko inne powinno działać. –

4

Innym rozwiązaniem, w zależności od rozmiaru pliku i systemu, z którego korzystasz, jest użycie memory mapped files, tj. mapowanie pliku do pamięci wirtualnej. To da ci bezpośredni dostęp do pliku, tak jakby był kawałkiem pamięci. W ten sposób dowolna liczba wątków może po prostu zapisać w regionie pamięci, a kolejne wywołania, aby opróżnić mapowanie na dysk (w zależności od konfiguracji odwzorowania pamięci) po prostu przechowują dane na dysku.

Należy zauważyć, że ze względu na ograniczenia adresowania na 32-bitowych platformach, nie będzie możliwe zmapowanie dowolnego pliku większego niż zwykle 2-3 GB, w zależności od architektury i faktycznej liczby bitów dostępnych do wykonania wirtualnego adresowanie pamięci. Większość 64-bitowych systemów ma 48 bitów lub więcej dostępnych dla tego zadania, co pozwala na mapowanie co najmniej 256 TB, które bym wziął to więcej niż wystarczające.

+0

Mam system operacyjny freebsd, więc, myślisz, że mogę używać mapowania pamięci ??? – Invictus

+0

Tak. Praktycznie wszystkie nowoczesne systemy UNIX obsługują mapowanie pamięci za pomocą funkcji 'mmap'. Strona _man_ podaje o wiele więcej szczegółów, które w twoim przypadku byłyby podobne (http://nixdoc.net/man-pages/FreeBSD/mmap.2.html). Generalnie wymagane kroki to po prostu otworzenie deskryptora pliku, jeśli to konieczne, wstępnie przydziel jego rozmiar (ręcznie lub przez fallocate lub posix_fallocate), a następnie zmapuj go do pamięci i gotowe. –

+0

Ale problem polega na tym, że używam tabeli mieszania do przechowywania danych przychodzących, i chcę to zapisać w pliku wyjściowym ... Czy istnieje jakiś sposób? – Invictus

Powiązane problemy