Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Checklist for thread-safe java on appengine

My java appengine project does not keep any state between requests except for the following uses of Memcache:

  • Objectify uses memcache to cache datastore gets
  • I use memcache as a way to batch cleanup tasks after multiple requests (e.g. if (the memcache doesn't think a cleanup task is already running) schedule another cleanup task).

I have no global / static references to any objects, except:

  • The current authenticated user is kept in a static ThreadLocal<User> object. This means each request will get its own copy of a User, right?
  • I have a class that handles all data manipulation, and an instance is kept as a sort of global variable in a static DataCoordinator object.

What do I need to look out for to make my code thread-safe? Do I need to throw a synchronized keyword into every method declaration in my DataCoordinator implementation, since multiple threads could access it? Is it true that the ThreadLocal<User> object will always make a separate User object for each thread, so that each request will be authenticated separately?

I'm a total newbie to thread-safe thinking. What should I read?

Thanks for any help, and sorry for the lack of specificity.

like image 865
Riley Lark Avatar asked Oct 30 '11 23:10

Riley Lark


People also ask

How do I know if a method is thread safe?

To test if the combination of two methods, a and b, is thread-safe, call them from two different threads. Put the complete test in a while loop iterating over all thread interleavings with the help from the class AllInterleavings from vmlens. Test if the result is either an after b or b after a.

How do I make a static method thread safe?

If you see Example 2 I am modifying 1st parameter. Now if you want to make this method really thread safe then one simple thing you can do. Either use non-mutable variables / objects or do not change / modify any method parameters.

What is thread Safety in servlet?

By default, servlets are not thread-safe. The methods in a single servlet instance are usually executed numerous times simultaneously up to the available memory limit. Each execution occurs in a different thread, though only one servlet copy exists in the servlet engine.

What data structures are thread safe in Java?

The collection classes that are thread-safe in Java are Stack, Vector, Properties, Hashtable, etc.


2 Answers

First thing you should be aware of is that app engine can replicate your application on multiple servers. That means your static variables will be unique only on one server. Thus your DataCoordinator will coordinate only the data access on a single server. So if you need common data to all servers running your app you should always use the data store for that (or gae HTTP session mechanism in some cases).

Regarding thread safety of DataCoordinator: You only need to synchronize methods of this coordinator if these methods are not implemented in a thread safe manner. For example you do not need to synchronize any methods that don't access any instance/static data but merely fetch data from the datastore. If methods access common instance/static data that is mutable (is also concurrently written) you can synchronize on a special monitor for the accessed data in most cases instead of synchronizing on the whole coordinator.

Regarding your ThreadLocal used to store auth token: You can do that (I do that for example for user authentication in gae for GWT request factory requests) and yes, every thread will have it's own variable value as long as you set it for that thread. Meaning it is best to make sure that the variable is set for each thread and it is adviceable to use a try-finally-block after setting it that eventually removes the authentication data after use. Why? Worst thing that could happen otherwise would be that a thread that belongs to user B's request still has an auth token of user A. That is because threads used in application server are usually pooled between requests instead of cleand up and recreated.

I cannot say anything about memcache since I have not used it.

Generally you have to be aware that any web requests (servlet/JSP/...) can be handled concurrently by the server. So any mutable shared resources that are accessed by those threads should be either synchronized or implemented in a thread safe manner.

Maybe http://download.oracle.com/javase/tutorial/essential/concurrency/ is a good starting point to read into it.

like image 178
Gandalf Avatar answered Sep 27 '22 16:09

Gandalf


If you have singleton classes, then only ONE instance will be created/used by your code per VM/Instance created.

A reference to this singleton can be fetched from:
- two sequential requests made one after another that are served by the same instance (depends on your settings how long they stay around, or if a reserved instance is running)
- two parallel requests running in separate threads on the same instance IF you have threadsafe set to true.

I have written and tested code to confirm this to myself, and deployed and tested. If code in one requests uses the singleton to modify one of its member variables, then it is modified for the other request running in parallel.

All logical really, once you figure out the lifetime of a VM and how many threads (only 1, or many) are used to serve incoming requests.

Also, System variables can be modified in code in one request and read in another...a second way two parallel requests/threads can interact.

See more details on this in my blog post on multi-threading in GAE/J here:
http://devcon5.blogspot.com/2012/09/threadsafe-in-appengine-gaej.html

like image 39
Andrew Mackenzie Avatar answered Sep 27 '22 16:09

Andrew Mackenzie