7

Potrzebuję pomocy w zrozumieniu synchronizacji - z relacją. Im więcej czytam, próbując zrozumieć przykład, tym bardziej czuję, że nic nie rozumiem. Czasami czuję, że to jest to, mam to, ale po obejrzeniu innego przykładu znowu się mylę. Proszę, pomóż mi to naprawić.synchronizuje się z semantyczną relacją, dzieje się przed i secesją uzyskującą

Mówi się, że operacja A synchronizuje się - z operacją B, jeśli A jest magazynem dla pewnej zmiennej atomowej m, z semantyką wyzwalającą, B jest obciążeniem z tej samej zmiennej m, z nabyciem semantyki, a B odczytuje wartość przechowywane A. mówi się również, że operacja typu a stanie, przed operacją z B jeśli

  • a jest wykonywane w ten sam gwint jak B i a jest przed B w kolejności programowej lub
  • a synchronizuje -z B, lub
  • A stało się - przed wykonaniem jakiejś innej operacji C i C - przed B

OK. Jeśli spojrzymy na ten przykład:

wątek0 wykonuje | Wątek1 wykonuje


przechowywać x (wydanie) | Obciążenie x (nabywać)

ma sklep do X-tu zsynchronizować z obciążeniem od X? Jeśli mamy tutaj synchronizację - z relacją, to zapisujemy do x dzieje się przed ładowaniem z x, więc wszystko, co jest zsekwencjonowane przed zapisaniem do x w wątku 0, dzieje się - przed załadowaniem z x w wątku 1. Oznacza to wymuszone porządkowanie tutaj. Czy to jest poprawne? Ale w tym przypadku nie rozumiem, co oznacza "i B czyta wartość przechowywaną przez A" część definicji? Jeśli wątek 1 jest szybszy, wątek 0 może odczytać starą wartość. Jaka jest tu relacja i czy istnieje jakiś związek? Jeśli nie ma, jak mogę zapewnić tę relację?

Z góry dziękuję.

+0

świetny artykuł jest tutaj http://preshing.com/20130823/the-synchronizes-with-relacja/ – camino

Odpowiedz

4

Nie mogę powiedzieć, że jestem dobrze zaznajomiony z terminologią, ale to jest, jak myślę, że idzie. Będę używał definicji .NET dla terminów: "Operacja uzyskała semantykę, jeśli inne procesory zawsze zobaczą jej efekt przed jakimkolwiek działaniem kolejnej operacji. Operacja ma semantykę wyzwalania, jeśli inne procesory zobaczą każdy efekt poprzedniej operacji przed efektem działania sama operacja. "

nie ma egzekwowane zamawianie między sklepu i obciążenia w przykładzie. Każda z nich może być wykonana jako pierwsza. Synchronizuje się z B, gdy operacja przechowywania zostanie wykonana przed załadowaniem. Gdy tak się stanie, wszystkie operacje przed magazynem (release) są gwarantowane do wykonania przed operacjami po załadowaniu (przejęciu).

Jednak operacja ładowania może zostać wykonana przed magazynem. W tym przypadku A nie synchronizuje się - z B (ponieważ warunek "i B odczytuje wartość zapamiętaną przez A" nie jest prawdą), więc operacje po załadowaniu mogą być wykonywane przed operacjami poprzedzającymi skład. Zamówienie jest niejasne.

Semantyka wydania gwarantuje, że dla pewnej wartości x będziemy wiedzieć, że operacje poprzedzające składnicę zostaną wykonane, zanim będziemy mogli załadować tę samą zapisaną wartość w drugim wątku (i zanim będziemy mogli wykonać operacje po obciążeniu).

Załóżmy, że liczba i flagi są inicjowane do zera i oba wątki prowadzone są równolegle:

thread0: 
st   count, 1 (A) 
st.release flag, 1 (B) 

thread1: 
ld.acquire flag  (C) 
ld   count  (D) 

Wiemy, że dzieje się, zanim B i C się dzieje, zanim D, ponieważ ich kolejność jest zmuszony przez uwolnienie i zdobycie semantyki. Kolejność B i C jest niezdefiniowana. Staje się ona zdefiniowana tylko wtedy, gdy B synchronizuje się - z C, a następnie wiemy, że A się dzieje - przed D (jak zdarza się A - zanim B się wydarzy - zanim C się wydarzy - przed D).

W wątku1 liczba ma zawsze wartość 1, jeśli flaga wynosi 1. Jeśli flaga ma wartość 0, liczba może wynosić 0 lub 1. Możemy przetestować flagę, aby ustalić, czy drugi wątek ustawił wartość na liczbę.

Bez semantyki przejmowania i uwalniania można ładować i magazynować zamówienia, a zarówno flaga, jak i licznik mogą być 0 lub 1 bez zależności.

Jeśli chcemy mieć pewność, że B się wydarzy - przed C możemy użyć semaforów lub innego mechanizmu oczekiwania i sygnału. W poprzednim przykładzie możemy wymusić kolejność zajętości - oczekiwanie na ustawienie flagi.

thread1: 
ld.acquire flag  (C) 
repeat C while flag == 0 
ld   count  (D) 
Powiązane problemy