čtvrtek 14. srpna 2008

Synchronizace kolem objektů v HTTP session

Rozečetl jsem knihu Java Concurrency in practice a jen tak letmo mezi stránkami mě napadlo, že většina webových aplikací, na kterých jsem dělal, vlastně byla thread safe jen tak na oko. Slabé místo představovaly objekty, které ležely v session a mohlo dojít k jejich současnému použití různými vlákny.

Servlet specifikace přímo říká:

Multiple servlets executing request threads may have active access to the same session object at the same time. The container must ensure that manipulation of internal data structures representing the session attributes is performed in a thread safe manner. The Developer has the responsibility for thread safe access to the attribute objects themselves.

Toto riziko se úměrně zvýšilo tím, jak se začaly používat aplikace postavené kolem AJAX konceptů. Tím totiž došlo k několika paralelním asynchronním voláním, které se typický zbíhaly v datech uložených v session. Je potřeba si uvědomit, že ačkoliv se to na první pohled nezdá, tak nesprávně řízený konkurenční přístup k datům v session může vést u aplikace k docela neočekávaným stavům, které v lepším případě končí například na zdánlivě nesmyslné NullPointerException výjimce. Na druhou stranu neřízené synchronizování všeho a na všem může vést k špatné škálovatelnosti aplikace.

Pro případ, kdy chceme opravdu vzájemné vyloučení, tedy serializovaný přístup k datům uvnitř session, tak bychom měli zvážit velikost zámku. Pokud se nepletu tak webový framework JBoss Seam umožňuje synchronizaci každého požadavku právě přes asociovanou session. To je v mnoha případech zbytečně velký zámek, proto se můžeme sami zasynchronizovat přímo na objektu, který se bude potenciálně mezi vlákny sdílet.

Pokud chceme zaručit pouze správnou viditelnost dat mezi vlákny a konkurenční přístup k nim nám nevadí pak můžeme použít volatile a nebo vhodné abstrakce na programové úrovni např. pro mapu zvolit jako implementaci ConcurrentHashMap.

Myslím si, že na správnou synchronizaci objektů sdílených přes session se v mnoha případech nemyslí, protože si to člověk neuvědomí a nebo se tiše ignoruje protože všechny důsledky nejsou patrné. Docela by mě zajímalo jestli to ve svých aplikacích řešíte a nebo to necháváte takzvaně koňovi s poukazem na "ono to už nějak dopadne".