File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Threads and Synchronization and the fly likes Servlet instance variables and volatile Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "Servlet instance variables and volatile" Watch "Servlet instance variables and volatile" New topic
Author

Servlet instance variables and volatile

chatchai chailuecha
Greenhorn

Joined: Dec 14, 2006
Posts: 18
Hi everybody,

Here is the code from SUN Java EE tutorial demonstrating how to initialize A Servlet.



Why bookDB hasn't been made volatile?
The variable bookDB has been set by a thread executing init() and later read by another thread that executing doGet().
Since it's not volatile so there is no guarantee that the thread executing doGet() will see the consistent value of the variable (or will see it at all).

Before I've learned about the concerns about java memory model, I also initialized Servlet this way and the code has been working quite well so far.

My question are that
1. Is the above code considered non-thread-safe both for old and new java memory model?
2. If it's not thread-safe then why it's been used pretty widely and it seems to work fine.
I've googled around and I couldn't find any source that strongly suggest using volatile in initializing Servlet instance variable from init() method.

Here is what I found in Concurrent Programming in Java
On most current JVM implementations and platforms, even those employing multiple processors, detectable visibility failures rarely occur.
The use of common caches across threads sharing a CPU, the lack of aggressive compiler-based optimizations, and the presence of strong cache consistency hardware
often cause values to act as if they propagate immediately among threads


So the above code is able to work as we expected just because the platform it's running on is exceptional smart?

Thanks in advance


Ireneusz Kordal
Ranch Hand

Joined: Jun 21, 2008
Posts: 423
chatchai chailuecha wrote:
Why bookDB hasn't been made volatile?
The variable bookDB has been set by a thread executing init() and later read by another thread that executing doGet().
Since it's not volatile so there is no guarantee that the thread executing doGet() will see the consistent value of the variable (or will see it at all).

Servlets can be started and run only by the web container (web server - like Tomcat, JBoss, WebSphere etc.).
Servlets cannot run as standalone java applications.
Requests from the client (from his web browser) are not serviced directly by the servlet, but are directed to the web server first,
and then the web server decides to which servlet this request should be passed.
The web containter load/initializes servlet (if it was not initlailized before), then passes the request to the servlet from the client.
The web container guarantees than the request cannot be passed to the servlet until servlet's initialization is finished
- so there is no need to explicitly synchronize code in the init() method.
Look here: http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/Servlets4.html

Requestts from the servlet to getServletContext().getAttribute("bookDB"); and getServletContext().setAttribute("bookDB", value);
are synchonized by the web container, so there is no need to synchronize this in the servlet code.
chatchai chailuecha
Greenhorn

Joined: Dec 14, 2006
Posts: 18
Ireneusz Kordal wrote:

The web container guarantees than the request cannot be passed to the servlet until servlet's initialization is finished
- so there is no need to explicitly synchronize code in the init() method.

Requestts from the servlet to getServletContext().getAttribute("bookDB"); and getServletContext().setAttribute("bookDB", value);
are synchonized by the web container, so there is no need to synchronize this in the servlet code.


Hi Ireneusz , thanks for your reply.
My concern is not about race condition and mutual exclusiveness. The problem is the visibility of the variable across multiple thread.

The bookDB variable has been updated by a thread and then later read by another thread. Although the Servlet container guarantee that
init() will be called before any thread enter doGet/doPost but ,according to java memory model, the thread executing doGet may not see
the updated value unless the variable is volatile.
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4181
    
  21

chatchai chailuecha wrote:
Ireneusz Kordal wrote:

The web container guarantees than the request cannot be passed to the servlet until servlet's initialization is finished
- so there is no need to explicitly synchronize code in the init() method.

Requestts from the servlet to getServletContext().getAttribute("bookDB"); and getServletContext().setAttribute("bookDB", value);
are synchonized by the web container, so there is no need to synchronize this in the servlet code.


Hi Ireneusz , thanks for your reply.
My concern is not about race condition and mutual exclusiveness. The problem is the visibility of the variable across multiple thread.

The bookDB variable has been updated by a thread and then later read by another thread. Although the Servlet container guarantee that
init() will be called before any thread enter doGet/doPost but ,according to java memory model, the thread executing doGet may not see
the updated value unless the variable is volatile.


That is not true - the memory model says the caches will be synched whenever a synchronization barrier is crossed, and volatile is a way of forcing a synchronization barrier (see the JMM for the side effects for volatile). From the Servlet spec we are told that the Servlet must complete the init() phase before any request can be processed, I haven't looked at the servlet spec to see if it states in more detail how this is performed, but in Java the only practical way to make sure that one section of code is processed before other threads can access other sections of code is through the use of synchronized blocks, which of course leads to synchronization barriers and synchronizing memory caches.


Steve
chatchai chailuecha
Greenhorn

Joined: Dec 14, 2006
Posts: 18
Steve Luke wrote:
That is not true - the memory model says the caches will be synched whenever a synchronization barrier is crossed, and volatile is a way of forcing a synchronization barrier (see the JMM for the side effects for volatile).

^
I think we have the same understanding about that.

Steve Luke wrote:
From the Servlet spec we are told that the Servlet must complete the init() phase before any request can be processed, I haven't looked at the servlet spec to see if it states in more detail how this is performed, but in Java the only practical way to make sure that one section of code is processed before other threads can access other sections of code is through the use of synchronized blocks, which of course leads to synchronization barriers and synchronizing memory caches.

^
Do you mean that Servlet containers usually have been implemented in a way that init() is called in a synchronized block and doGet() is also called in
a synchronized block of the same monitor so there will be memory caches synchronizing once a request thread enter doGet()?
Vijitha Kumara
Bartender

Joined: Mar 24, 2008
Posts: 3833

chatchai chailuecha wrote:Do you mean that Servlet containers usually have been implemented in a way that init() is called in a synchronized block

Before any request is routed to a particular servlet it should be initialized (that is instantiated and the init() method completed)
and doGet() is also called in a synchronized block of the same monitor so there will be memory caches synchronizing once a request thread enter doGet()?

I don't think it's necessary as each request is served by a separate thread.


SCJP 5 | SCWCD 5
[How to ask questions] [Twitter]
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4181
    
  21

chatchai chailuecha wrote:
Do you mean that Servlet containers usually have been implemented in a way that init() is called in a synchronized block and doGet() is also called in
a synchronized block of the same monitor so there will be memory caches synchronizing once a request thread enter doGet()?


No, that would be a bad thing to put the request into a synchronized block, you would lose the ability to run simultaneous requests. I won't say anything about how it is usually implemented, because I don't know. But if I were doing it I would make a small call to something like waitForInit() in a synchronized block so each thread, while checking to see if the init() method is complete, would pass through a memory barrier. This would be necessary anyway since synchronization is the only way to get the request threads to wait for the init() to complete, should they be called prematurely.
Chris Hurst
Ranch Hand

Joined: Oct 26, 2003
Posts: 417
    
    2

I've had a quick look at a servlet spec (not the latest) and it doesn't seem to guarantee happens before ordering though init will execute in a single thread prior to get / put as you say that wouldn't guarantee visibility on its own (if anyone has found some documentation on this post please), though I would expect a container to honour this. I guess another way they could achieve this would be have the init thread terminate and all request threads be created after the init thread which would give you the appropriate sequence points but that doesn't seem that efficient (thread creation / destruction).

PS Synchronizing put / get would give you the SingleThreadModel not recommended.


"Eagles may soar but weasels don't get sucked into jet engines" SCJP 1.6, SCWCD 1.4, SCJD 1.5,SCBCD 5
 
GeeCON Prague 2014
 
subject: Servlet instance variables and volatile