2015-08-12 15 views
5

I określonych zmiennej (r.something) wewnątrz przedmiotuCzy wymagana jest synchronizacja?

func (r *Runner) init() { 
    r.something = make(map[string]int) 
    r.something["a"]=1 

    go r.goroutine() 
} 

podczas r.goroutine wykorzystuje wartości przechowywanej w r.something bez synchronizacji. Nikt inny nie odczyta/zapisze tej wartości z wyjątkiem r.goroutine()

Czy można to zrobić bez synchronizacji?

Innymi słowy: chcę ponownie użyć jakiejś zmiennej z goroutiny zainicjowanej gdzie indziej przed początku goroutine. Czy to jest bezpieczne?

Dodatkowe pytanie: Po zakończeniu r.goroutine() chcę móc używać r.something z innych źródeł (bez nakładania się odczytu/zapisu z innymi goroutinami). Czy to też jest bezpieczne?

Odpowiedz

5

Oczywiście jest to bezpieczne, ponieważ programowanie w Go może być koszmarem (a przynajmniej znacznie mniej przyjemnym). The Go Memory Model to interesujący fragment do przeczytania.

Tworzenie rutyny jest punktem synchronizacji. Jest to przykład bardzo podobny do Ciebie:

var a string 

func f() { 
    print(a) 
} 

func hello() { 
    a = "hello, world" 
    go f() 
} 

z następującym komentarzem:

nazywając cześć drukuje „Hello, World” w pewnym momencie w przyszłości (być może po powrocie z komentarzy).

To dlatego, że:

Oświadczenie Go, który rozpoczyna nowy goroutine dzieje przed zaczyna Wykonawczym goroutine użytkownika.

Słowo przed jest kluczowe tutaj, ponieważ implikuje rutynowe tworzenie (w jednym wątku) muszą być zsynchronizowane z jego rozpoczęcia (ewentualnie w innym wątku), więc pisze do musi być widoczny przez nową rutynę .

+0

Całkowicie ma sens! Dzięki @tomasz – let4be

3

Jeśli nie istnieje sytuacja, w której pokrywają z czytać i pisać operacji według różnych Go-rutyny może wystąpić w tej zmiennej, to masz rację: nie ma potrzeby jakiegokolwiek synchonization.

Jak już wspomniałeś, że zmienna została zainicjowana przed twoja rutyna się rozpoczęła, jesteś w rzeczywistości bezpieczny.

+0

Co powiesz na to, że zmienne zmodyfikowane w jednym z wątków systemu operacyjnego mogą nie być widoczne z innego wątku systemu operacyjnego, chyba że dostęp zostanie zawarty w jawnej synchronizacji, takiej jak synchronizacja.Maneks. Wiem, że mówimy o goroutinach, ale pod maską idzie do wątków systemu operacyjnego, choć nie zawsze. W jaki sposób ma on związek ze zmienną inicjalizacją przed rozpoczęciem goroutine, czy golang wykonuje niejawną synchronizację przechwyconych zmiennych gdzieś w środku przed rozpoczęciem goroutine? – let4be

+1

Musimy precyzyjnie określić termin "widoczny": Oczywiście zmienna jest widoczna (jak w: widocznym w ogóle) dla każdego wątku danego procesu. Problem polega na tym, że jest ** zmiana ** wykonana przez wątek A widoczny dla wątku B ** na czas **. Może się tak nie zdarzyć, jeśli dwa wątki uzyskują dostęp do zmiennej ** równocześnie **. Ale jako pierwszy wątek (używam go jako synonim do rutynowych czynności: dwa zachowują się bardzo podobnie) długo kończył modyfikacje, zanim jeszcze drugi istnieje, jesteśmy bezpieczni. Nie ma żadnej niejawnej synchronizacji przez środowisko wykonawcze go, niejawna synchronizacja jest wykonywana przez twój kod. –

1

Tak, jest bezpiecznie. Według Go Memory Model:

  • oświadczenie Go, który rozpoczyna nowy goroutine dzieje przed rozpoczęciem Wykonawczym goroutine za
  • obrębie jednego goroutine The dzieje, zanim zamówienie jest kolejność wyrażone przez program

Oznacza to, że wszystkie zmiany w zmiennych, które wprowadziłeś przed uruchomieniem goroutine, są widoczne wewnątrz tej goroutine.

Odpowiedz na dodatkowe pytanie: to zależy. Ogólnie rzecz biorąc, jeśli r.goroutine() zmodyfikowany r.goroutine() i chcesz go odczytać z innej goroutine, musisz użyć synchronizacji.

Powiązane problemy