Question

I have rather general question, please advice.

I have a servlet.

This servlet has private field.

Private field is a kind of metadata stuff (public class Metadata{//bla-bla-bla}).

When GET request is processed, this metadata is used to perform some operation.

I want to implement POST method in the same servlet. User uploads file and Metadata field is updated.

The problem: concurrent access to this private field with Metadata object shared among sereval web-threads using one servlet instance. POST method operaton (Update Metadata object) can lead to Metadata inconsistent state and concurrent GET request can be failed.

The question: what is the best way to update Metadata object while GET requests are running?

Dummy solution:

  1. During each GET request,, at the very beginning

  2. Synchonize Metadata object and clone it in one block, then release it.

  3. Concurrent GET requests work with clone verstion of Metadata object which is consistent.

  4. During each POST request.

  5. Synchonize Metadata object and update its fields.

  6. Release Metadata object.

Please advice or critisize.

Was it helpful?

Solution

Using synchronized methods set and get in the Metadata class is fine but may slower your web app in case you have multiple readers and (much) less writers:

Java synchronized keyword is used to acquire a exclusive lock on an object. When a thread acquires a lock of an object either for reading or writing, other threads must wait until the lock on that object is released. Think of a scenerio that there are many reader threads that reads a shared data frequently and only one writer thread that updates shared data. It’s not necessary to exclusively lock access to shared data while reading because multiple read operations can be done in parallel unless there is a write operation.

(Excerpt from that nice post)

So using a multiple read single write strategy may be better in term of performance in some cases as explained also in the same Java5 ReadWriteLock interface doc:

A read-write lock allows for a greater level of concurrency in accessing shared data than that permitted by a mutual exclusion lock. It exploits the fact that while only a single thread at a time (a writer thread) can modify the shared data, in many cases any number of threads can concurrently read the data (hence reader threads). In theory, the increase in concurrency permitted by the use of a read-write lock will lead to performance improvements over the use of a mutual exclusion lock. In practice this increase in concurrency will only be fully realized on a multi-processor, and then only if the access patterns for the shared data are suitable.

Whether or not a read-write lock will improve performance over the use of a mutual exclusion lock depends on the frequency that the data is read compared to being modified, the duration of the read and write operations, and the contention for the data - that is, the number of threads that will try to read or write the data at the same time. For example, a collection that is initially populated with data and thereafter infrequently modified, while being frequently searched (such as a directory of some kind) is an ideal candidate for the use of a read-write lock. However, if updates become frequent then the data spends most of its time being exclusively locked and there is little, if any increase in concurrency. Further, if the read operations are too short the overhead of the read-write lock implementation (which is inherently more complex than a mutual exclusion lock) can dominate the execution cost, particularly as many read-write lock implementations still serialize all threads through a small section of code. Ultimately, only profiling and measurement will establish whether the use of a read-write lock is suitable for your application.

A ready to use implementation is the ReentrantReadWriteLock.

Take a look at the previous post for a nice tutorial on how to use it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top