2012-04-04 9 views
6

Używam this approach do przechowywania danych w globalnej tablicy obsługującej serwer http, gdzie niektóre żądania będą manipulować globalną tablicą.Które operacje w węźle są bezpieczne dla wątków?

Trochę się martwię o problemy z wątkami w niektórych operacjach - głównie push i splice. Wyobrażam sobie, że jeśli jedna z żądań ma mnie powtarzać przez tablicę i usuwać elementy w oparciu o warunki warunkowe, podczas gdy inna prośba wzywa mnie do wywoływania .push() w tablicy, w której napotkasz problemy. Czy ktoś może to potwierdzić?

Przeważnie piszę w języku C#, gdzie nawet prosty przyrost nie jest bezpieczny dla wątków (uruchomienie 25 wątków, które wykonuję i ++, nie gwarantuje, że i == 25 po tym jak wszystko zostanie powiedziane i zrobione).

Aktualizacja:

Pisałem 5 przykłady pokazują, co mówię. Test 1 i Test 3 działają bez zarzutu. Test 2 kończy się niepowodzeniem, ze względu na ... co normalnie nazywałoby się problemami z gwintowaniem (niezależnie od tego, czy są to rzeczywiste wątki procesora, czy nie). Testy 4 i 5, gdy działają równolegle, wydają się działać (co oznacza, że ​​nie mają problemów z kolizją, takich jak Test 2).

http://pastebin.com/HcJHTDFY

Używam apachebench przetestować, czyniąc 1000 równoległych żądań.

To prowadzi mnie do przypuszczenia, że ​​test 1 test 3 i działać poprawnie ponieważ nodejs nie będzie wykonywał więcej niż 1 wystąpienie app.get('/test3'...) zwrotnego równolegle javascript funkcja równolegle (blokowanie?). Jak tylko zaimplementujesz setInterval/setTimeout, zwalnia on nodejs do wykonania innej instancji wywołania zwrotnego (bez blokowania?).

Naprawdę tylko staram się zrozumieć, co naprawdę oznacza ten cholerny non-blocking I/O model. Czy to oznacza, że ​​"hej, nie można blokować za pomocą setTimeout i setInterval, jeśli nie potrzebujesz blokowania, w przeciwnym razie zablokujemy inne funkcje zewnętrzne, dopóki nie wyczerpiemy funkcji, na której działamy" ? Czuję, że trzeba to wiedzieć, aby nie wpakować się w kłopoty, myśląc, że mogę wprowadzić coś w stylu/test2 i być całkowicie bezpieczne.

Również jeśli próbuję być bez blokowania z moich połączeń zwrotnych, czy naprawdę powinienem dzwonić setTimeout(code, 1)? Czy jest jakiś lepszy sposób?

Odpowiedz

10

Wszystkie są bezpieczne dla wątków.

Brak wątków, JavaScript jest jeden wątek, niemożliwe jest uruchomienie dwóch instrukcji javascript w tym samym czasie.

Tak na marginesie, nie należy używać globalnych i tak ponieważ globalne są złe

Edit:

Test 2 nie działa, ponieważ używasz asynchronicznych wywołań zwrotnych, co oznacza kontrolę wraca do węzła i może obsłużyć więcej żądań. To stwarza warunki wyścigu, jak widać.

W węźle wszystko, co nie jest blokowane asynchronicznie. Jedyne asynchroniczne rzeczy, które masz, to setTimeout/setInterval/process.nextTick i wszelkie asynchroniczne operacje IO.

Nie należy ręcznie wykonywać obliczeń asychronicznie.Trzeba po prostu unikać zbyt wielu obliczeń.

pisałem artykuł o What it means to be non-blocking

+0

Więc gdy nodeJs/V8 dostanie się do funkcji() {} Napisałem, żadne inne moje funkcje nie zostaną wykonane, z wyjątkiem tych, które nazywam wewnątrz (jako callbacki)? – Langdon

+0

Nawiasem mówiąc, JavaScript może być pojedynczy wątek, ale nodeJS wydaje się być wielowątkowy, w przeciwnym razie kolejne żądania do wbudowanego serwera http nie będą w stanie powrócić, dopóki pierwszy nie zostanie zakończony. Również http://stackoverflow.com/questions/7018093/nodejs-really-single-threaded – Langdon

+0

@Langdon czy to wielowątkowe czy nie jest szczegółem implementacji, którego nie powinno się obchodzić. Wszystko, co robi, to asynchroniczne IO, bezpośrednio na poziomie jądra lub emulowane asynchroniczne IO przy użyciu puli wątków – Raynos

-5

Raynos jest najczęściej prawidłowa. Ale tylko dlatego, że JavaScript jest pojedynczy wątek, nie oznacza, że ​​możesz pozwolić swoim strażnikom w dół. Nadal musisz być świadomy wątków. Dobrym przykładem ilustrującym to jest to, w jaki sposób socket.io utrzymuje połączenie z różnymi klientami i nadal może śledzić tych klientów.

Część funkcjonalna programowania JavaScript działa poprzez powiązanie zmiennej (np. ... DUŻO). Nieświadomość wątków powoduje, że błędnie zakładasz, że zmienne są poprawnie powiązane. Podobnie jak w przypadku przykładu dotyczącego socket.io, jak możesz mieć pewność, że połączenie, które otrzymujesz, jest klientem, który myślisz, że dostajesz? Co się stanie, jeśli powiązanie referencyjne poszło nie tak i połączenie faktycznie odwołuje się do innego klienta?

Jest to typ rzeczy, których należy uważać.

+1

JavaScript nie ma przejścia przez odniesienie. To i nonsens, o którym mówisz, nie ma nic wspólnego z wątkami. node.js nawet nie używa wątków, jeśli system operacyjny obsługuje asynchroniczne IO na poziomie jądra – Raynos

+0

@lightblade Haters ... – Langdon

+1

Aby przekazać rzeczywistą informację zwrotną/krytykę. Kiedy "powiązanie referencyjne pójdzie źle". Kiedy połączenie wskazywałoby innego "klienta". Tak, istnieją pułapki współbieżne, o których powinieneś wiedzieć, ale ich nie opisujesz i nie są powiązane z wątkami. – Raynos

Powiązane problemy