-
Path: news-archive.icm.edu.pl!agh.edu.pl!news.agh.edu.pl!newsfeed2.atman.pl!newsfeed.
atman.pl!.POSTED!not-for-mail
From: Edek <e...@g...com>
Newsgroups: pl.comp.programming
Subject: Re: pytanie z mutexów
Date: Tue, 2 Jul 2013 17:56:21 +0000 (UTC)
Organization: ATMAN - ATM S.A.
Lines: 126
Message-ID: <kqv484$hb1$7@node2.news.atman.pl>
References: <5...@g...com>
<51c56394$0$28103$c3e8da3$91613603@news.astraweb.com>
<f...@4...com>
<kq70gf$ngh$1@mx1.internetia.pl>
<3...@4...com>
<kq7g4r$a05$1@mx1.internetia.pl>
<f...@4...com>
<kqi854$v85$1@mx1.internetia.pl>
<u...@4...com>
<kqk43i$sfo$1@mx1.internetia.pl>
<a...@4...com>
<kqqbud$j5h$1@mx1.internetia.pl> <kqqg26$pa6$8@node2.news.atman.pl>
<kqrkrs$ka6$1@mx1.internetia.pl> <kqrnjk$fgq$1@node2.news.atman.pl>
<kqsb2s$t1t$1@mx1.internetia.pl> <kqsd2l$fgq$5@node2.news.atman.pl>
<kquuvu$c01$1@mx1.internetia.pl>
NNTP-Posting-Host: 87-205-33-79.adsl.inetia.pl
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
X-Trace: node2.news.atman.pl 1372787781 17761 87.205.33.79 (2 Jul 2013 17:56:21 GMT)
X-Complaints-To: u...@a...pl
NNTP-Posting-Date: Tue, 2 Jul 2013 17:56:21 +0000 (UTC)
User-Agent: Pan/0.139 (Sexual Chocolate; GIT bf56508 git://git.gnome.org/pan2)
Xref: news-archive.icm.edu.pl pl.comp.programming:203942
[ ukryj nagłówki ]Dnia pamiętnego Tue, 02 Jul 2013 18:16:18 +0200, Michoo wyjmując peta
oznajmił:
> On 01.07.2013 19:08, Edek wrote:
>> Dnia pamiętnego Mon, 01 Jul 2013 18:24:17 +0200, Michoo wyjmując peta
>> oznajmił:
>>> Co do samego algorytmu - potrzebne są trzy stany:
>>> przed_inicjalizacją, w_trakcie, po_inicjalizacji, nie da się tego zrobić
>>> na JEDNEJ fladze binarnej, można by użyć dwóch(i wprowadzić odpowiednie
>>> poprawki), ale po co?
>>
>> Nie, jest potrzebna monotonicznie rosnąca liczba, nie trzy stany. Mi
>> to zajęło z pół godziny żeby dojść dlaczego: spróbuj zastąpić
>> monotonicznie rosnącą stanami i albo udowodnij poprawność
>> albo udowodnij że jest problem.
>
> #define START_VALUE 2
> #define BEING_INITIALIZED 1
> #define INIT_DONE 0
>
> /* PRECONDITION:
> *once == START_VALUE
> */
>
> void fast_pthread_once( fast_pthread_once_t *once, void (*func)(void) )
> {
> /*01*/ if ( *once != INIT_DONE ) {
> /*02*/ check( pthread_mutex_lock(&mu) == 0 );
> /*03*/ if ( *once == START_VALUE ) {
> /*04*/ *once = BEING_INITIALIZED;
> /*05*/ check( pthread_mutex_unlock(&mu) == 0 );
> /*06*/ (*func)();
> /*07*/ check( pthread_mutex_lock(&mu) == 0 );
> /*08*/ *once = INIT_DONE;
> /*09*/ check( pthread_cond_broadcast(&cv) == 0 );
> /*10*/ } else {
> /*11*/ while ( *once != INIT_DONE ) {
> /*12*/ check( pthread_cond_wait(&cv, &mu) == 0 );
> /*13*/ }
> /*14*/ }
> /*15*/ check (pthread_mutex_unlock(&mu) == 0);
> /*16*/ }
> }
>
> Wszystkie zapisy i odczyty (poza linią 01) są chronione muteksem. Tak więc:
> A) w lini 01 może zostać albo odczytana wartość początkowa, wartość z
> linii 04 lub 08
> - w przypadku odczytu INIT_DONE pomijamy cały blok - inicjalizacja
> została już wykonana
Tak, ale nie miała miejsce synchronizacja.
> - w przypadku odczytu innej wartości rozpoczynamy blok synchronizowany B
>
> B) w linii 03 może zostać albo odczytana wartość początkowa, wartość z
> linii 04 lub 08
> - w przypadku wartości innej niż START_VALUE oczekujemy w liniach 11,12
> na zakończenie inicjalizacji [*] (deadlock przy wywołaniu rekurencyjnym)
> - w przypadku wartości START_VALUE zmieniamy ją na BEING_INITIALIZED i
> kończymy blok synchronizowany - od tego momentu żaden wątek w 01 ani 03
> nie odczyta wartości START_VALUE
> - Po zakończeniu inicjalizacji zapisujemy *once = INIT_DONE i wybudzamy
> wątki czekające w linii 12 - od tego momentu nie zostanie odczytana inna
> wartość niż INIT_DONE
>
> Czekające wątki po kolei kończą oczekiwanie 12->11->15.
>
> [*] Jeżeli wartość zmieniła się na INIT_DONE po odczycie w linii 01 ale
> przed otrzymaniem muteksu to nie czekamy w linii 12 tylko kończymy na 15.
>
> Pisane na szybko więc co przeoczyłem?
Model pamięci C++11?
>> Ja potrafię to drugie.
>>
> Poproszę.
Model Pamięci ma taką cechę że zapis w wątku A jest widoczny w wątku B
gdy nastąpi uszeregowanie poprzez release w A i acquire w B. Lock() to
aquire, unlock() to release, albo można w ogóle każdą operację na
mutexie traktować 'stricter' jako sequence point - czyli jeżeli oba
wątki przejdą op na mutex to zapis w A może być odczytany w B. Jeżeli
nie ma przejścia przez mutex obu wątków mamy race, czyli wątek B
czyta potencjalnie śmieci. Zapis dotyczy zmiennych użytych tutaj i wszystkich
zapisów w func(), które po przejściu algorytmu muszą być widoczne.
func to głównie konstruktory, przejście całego algorytmu oznacza,
że obiekty są już zainicjalizowane (przez wywołanie func).
Uff, definicje z głowy ;). Wątek A i wątek B i numery linii,
możliwa sekwencja:
A linie 1 do 5 (w 2 i 5 jest mutex)
A 6: konstruktor (po to jest ten algorytm) może zapisać pola
A 7: mutex (acquire)
A 8: once = INIT_DONE
B 1: (once == INIT_DONE) == true (co nie musi być prawdą, ale może)
B 17: wątek używa wartości z A 6, które nie muszą być poprawne,
bo wątek B nie przeszedł przez żaden mutex. Może odczytać
śmieci, czyli mamy race
Powyższa sekwencja może jest mało prawdopodobna, ale mamy
data race.
Na Intelach jeżeli dobrze kojarzę to się nie ma prawa zdarzyć,
bo Intel ma taki model pamięci że jeżeli zapis do once jest widoczny
to poprzednie zapisy z func też, były wcześniej. Pisząc asma x86 można
na tym polegać, ale w bibliotece taki algorytm w C na innej platformie
nagle ma niewidoczne efekty konstruktorów. Przynajmniej wg. modelu
pamięci C11 i C++11.
W oryginalnym algorytmie zawsze będzie odpowiedni 'ordering' przez
synchronizację, bo ta zmienna thread-local jest zmieniana tylko
przy zankniętym mutex, więc pierwszy if bez przejścia przez mutex
nigdy nie będzie false. Dlatego ten algorytm jest genialny, kolejne
przejścia są bez synchronizacji.
Pozdrawiam
--
Edek
Następne wpisy z tego wątku
- 02.07.13 21:18 Michoo
- 02.07.13 23:06 Edek
- 03.07.13 02:29 Michoo
- 03.07.13 04:08 Edek
- 09.07.13 14:42 firr
- 10.07.13 15:41 firr
Najnowsze wątki z tej grupy
- 7. Raport Totaliztyczny: Sprawa Qt Group wer. 424
- TCL - problem z escape ostatniego \ w nawiasach {}
- Nauka i Praca Programisty C++ w III Rzeczy (pospolitej)
- testy-wyd-sort - Podsumowanie
- Tworzenie Programów Nieuprzywilejowanych Opartych Na Wtyczkach
- Do czego nadaje się QDockWidget z bibl. Qt?
- Bibl. Qt jest sztucznie ograniczona - jest nieprzydatna do celów komercyjnych
- Co sciaga kretynow
- AEiC 2024 - Ada-Europe conference - Deadlines Approaching
- Jakie są dobre zasady programowania programów opartych na wtyczkach?
- sprawdzanie słów kluczowych dot. zła
- Re: W czym sie teraz pisze programy??
- Re: (PDF) Surgical Pathology of Non-neoplastic Gastrointestinal Diseases by Lizhi Zhang
- CfC 28th Ada-Europe Int. Conf. Reliable Software Technologies
- Młodzi programiści i tajna policja
Najnowsze wątki
- 2024-11-24 Aby WKOOOORWIĆ ekofaszystów ;-)
- 2024-11-22 OC - podwyżka
- 2024-11-22 wyszedł z domu bez buta
- 2024-11-22 Bieda hud.
- 2024-11-24 DS1813-10 się psuje
- 2024-11-23 Białystok => Inżynier bezpieczeństwa aplikacji <=
- 2024-11-23 Szczecin => QA Engineer <=
- 2024-11-23 Warszawa => SEO Specialist (15-20h tygodniowo) <=
- 2024-11-22 Warszawa => Kierownik Działu Spedycji Międzynarodowej <=
- 2024-11-22 Warszawa => Senior Account Manager <=
- 2024-11-22 Warszawa => Key Account Manager <=
- 2024-11-22 Warszawa => DevOps Specialist <=
- 2024-11-22 Kraków => IT Expert (Network Systems area) <=
- 2024-11-22 Warszawa => Infrastructure Automation Engineer <=
- 2024-11-22 Warszawa => Presales / Inżynier Wsparcia Technicznego IT <=