def startup
Thread.current[:user] = current_user
Thread.current.thread_variable_set(‘user’, current_user)
end[/code]
Które przypisanie w metodzie startup wykorzystać? Z opisu w active_support/core_ext/thread.rb wynika że raczej ten drugi zapis ale …
W wszystkich opisach Rails4 trąbią, że Rails jest teraz “threadsafe” ale co to właściwie oznacza? Wydawało mi się, że oznacza to, że dane z poszczególnych wątków nie będą się mieszać a tu już pierwszy problem przy zmiennej klasowej bo wychodzi na to, że klasy są wspólne dla wątków. Co zatem oznacza “threadsafe”? Które elementy aplikacji są wspólne dla wszystkich wątków a które odizolowane w ramach wątku? Jeżeli w opisach widzę że @zmienna += 1 nie jest “threadsafe” to jak mam zrealizować jakikolwiek licznik?
Chodzi o to że po zakończeniu przetwarzania jednego zapytania część serwerów używa tego samego wątku do przetworzenia kolejnego zapytania. Więc niektóre dane mogę “przecieknąć” pomiędzy zapytaniami. Mówię tu tylko i wyłącznie o zawartości Thread.current.
Zmienne klasowe są wspólne dla wszystkich wątków.
[quote=Tuptus][quote=Świstak]@tuptus przy thread current musisz wiedzieć że:
Każdy request ma jeden wątek.
Z tym że kilka requestów może mieć jeden wątek.[/quote]
Pierwsze rozumiem ale to drugie??? Kilka requestów działa na tym samym wątku???[/quote]
Aplikacja może działać na 2 sposoby
a) dla każdego requestu odpalany jest nowy wątek, po obsłużeniu requestu wątek jest zabijany
b) każdy proces odpala ustaloną liczbę wątków i te wątki działają przez cały czas działania aplikacji, po obsłużeniu requestu biorą następny.
W tym drugim przypadku rzeczywiście Thread.current będzie wspólne dla wielu zapytań (kolejnych, nie równoległych)
To drugie to tylko alias, spójrz na implementację.
Oznacza to tyle, że możesz uruchomić railsy na wielu wątkach i struktury używane w railsach będę odporne na odpalanie równolegle.
To jest kwestia tego jak działa ruby.
Poczytaj sobie więcej o wątkach Np. http://www.jstorimer.com/products/working-with-ruby-threads. Wszystkie rzeczy, do których możesz dostać się z więcej niż jednego wątku mogą potencjalnie nie być threadsafe. W praktyce odnosi się to głównie do zmiennych globalnych, klas, metod/zmiennych klasowych (przynajmniej jeżeli chodzi o akcje w kontrolerach)
A licznik możesz zrobić używając Mutex:
[code]class MyClass
class << self
@@counter_mutex = Mutex.new
def increment
@@counter_mutex.synchronize do
@counter += 1
end
end
To drugie to tylko alias, spójrz na implementację.
Oznacza to tyle, że możesz uruchomić railsy na wielu wątkach i struktury używane w railsach będę odporne na odpalanie równolegle.[/quote]
Ale pewnie nie dotyczy to starych dobrych tablic, i innych rubiowych struktur, nie? W sensie `array << :bla’ z wielu wątków może być nadal problemem?
To chyba zależy gdzie używasz tych tablic. Z tego artykułu http://yehudakatz.com/2010/08/14/threads-in-ruby-enough-already/ akapit “Threads are just HARD” wynika, że kod w kontrolerze oraz modelach, które są inicjalizowane w tychże kontrolerach nie są współdzielone.
Mam na myśli zmienne globalne lub/i instancji klasy. Wtedy jest potrzeba używać mutexów nawet w Railsach, więc informacja o thread safe nie jest precyzyjna…