Chlorek Temat założony przez niniejszego użytkownika |
Dodanie do programu zabezpieczenia thread-safe » 2013-02-25 19:52:08 Piszę pewien program, który wykorzystuje kilka wątków, które operują na złożonych typach i klasach, w związku z tym zapis i odczyt pewnych wartości momentami kolidowały. Postanowiłem więc dodać zabezpieczenie, pomyślałem początkowo o użyciu CriticalSection, ale żadnego efektu nie zauważyłem. Dlatego pomyślałem jaka operacja zajmuje jak najmniej czasu procesora, wpadłem na pomysł utworzenia zmiennej bool, która będzie przetrzymywała status wykonania jakiejś części kodu w programie. Napisałem kod, który wygląda mniej-więcej tak: bool state = false;
void func() { while( state ); state = true; state = false; }
Co prawda mój kod wygląda nieco inaczej w praktyce ale chodzi o pokazanie zasady działania. I teraz mam pytanie - trick daje zamierzony efekt, ale nie mam pewności co do tego czy na pewno jest to w pełni bezpieczne? W teorii zawsze gdy jakiś wątek wejdzie do funkcji i ustawi 'state' na 'true' to każdy kolejny wątek czeka do zakończenia działania pierwszego wątku w tej części kodu i to właśnie on potem znowu rezerwuje działanie na pewnych zasobach programu. Jeśli można to zrobić lepiej i efektywniej chętnie posłucham wskazówek. |
|
DejaVu |
» 2013-02-25 20:03:50 Do takich rzeczy używa się sekcji krytycznych... mając fizycznie dwa rdzenie istnieje prawdopodobieństwo, że oba porównania while zajdą w tym samym czasie i opuszczą pętlę przez co dwa wątki będą wykonywały ten sam kod z różnymi danymi wejściowymi. |
|
Chlorek Temat założony przez niniejszego użytkownika |
» 2013-02-25 20:14:43 W takim razie jak poprawnie użyć sekcji krytycznych? Robiłem do tej pory to tak: CRITICAL_SECTION section;
int func() { EnterCriticalSection( & section ); LeaveCriticalSection( & section ); }
A z InitializeCriticalSection(§ion) miałem problemy - wywołanie na początku programu powodowało crash aplikacji, jedyne miejsce w którym aplikacja nie crashowała to miejsce przed EnterCriticalSection(). Może właśnie dlatego ten sposób nie działał. |
|
pekfos |
» 2013-02-25 20:31:58 Można też użyć mutexów z biblioteki standardowej C++11. |
|
DejaVu |
» 2013-02-25 20:35:40 No bo sekcję krytyczną trzeba jeszcze zainicjalizować. Użyj boost::scoped_lock jeżeli masz skonfigurowaną tą bibliotekę i po problemie. Albo poszukaj tutoriala do WinAPI jak obsługiwać sekcję krytyczną bądź jakiś przykład. Na pewno jest ich sporo w necie. |
|
Chlorek Temat założony przez niniejszego użytkownika |
» 2013-02-25 20:42:40 Do tego trzeba używać C++11, a mój projekt ma już swój czas (rozpocząłem prace ok. pół roku temu), dodatkowo mój program można nazwać dwoma programami w jednym (w zależności od argumentów pełni rolę aplikacji serwer lub klient). Wtedy zaczynając pisanie nie myślałem o tym jakiego standardu użyć, sam w sumie słabo jeszcze wtedy znałem standard C++11, a tym bardziej bibliotekę boost. Aktualnie mój projekt nie skompiluje się pod C++11, bez wielu, na prawdę wielu poprawek. Dlatego pozostaje WinAPI zamiast boosta. W przyszłości pewnie będę przepisywał program używając bibliotek ze wsparciem na różne inne platformy, ale tylko w przypadku jeśli mój program na prawdę wypali i w ogóle będzie to opłacalne. |
|
DejaVu |
» 2013-02-25 20:44:33 Osobiście polecam zgłębiać WinAPI i trzymać się WinAPI, aniżeli pchać się na siłę w biblioteki przenośne. Doświadczenie mówi, że ważniejsze jest ukończenie projektu nad ideologie typu 'przenośność kodu', które często potrafią komplikować życie :) |
|
Chlorek Temat założony przez niniejszego użytkownika |
» 2013-02-25 20:51:32 Aktualnie pozostanę przy WinAPI i innych bibliotekach z których korzystam. Jednak z uwagi na to że program wykorzystuje już teraz wiele przenośnych bibliotek (między innymi OpenGL), a część programu to serwer (a wiadomo, jak serwer to dobrze byłoby dać support na linuxa). Przy okazji zapytam, jak to jest z WinSock? - coś kiedyś słyszałem, że działa również pod linuxem. To prawda? |
|
« 1 » 2 |