This week's book giveaway is in the OCAJP forum. We're giving away four copies of OCA Java SE 8 Programmer I Study Guide 1Z0-808 and have Jeanne Boyarsky & Scott Selikoff on-line! See this thread for details.
... which claims that congestion in webapps results unavoidably when using tomcat's Database Connection Pooling, given synchronized access to the pooled connections:
"Having even a single synchronized block of code executed by every incoming request may bring your application to its knees with no more than 5 simultaneous users as only one thread can execute a synchronized block of code while other threads remain suspended until they can obtain a lock."
Proposed solutions to this are limited to roll-your-own ThreadLocal() code, and Spring ThreadLocal() code, that latter being the point of the article.
Thoughts on this? Really brought to one's knees with 5 users ??
The roll-your-own approach mentioned:
"Some clever people have come up with a solution by adding a filter in the servlet container configuration. Such a filter would amongst other things create a JDBC connection or Hibernate session at the start of the request before the web tier is invoked and bind it to the current thread by means of ThreadLocal for use in the business logic."
... is certainly clever, but is it not possible to gain a performance improvement more simply by wrapping connection requests in a ThreadLocal() within the DAO? something like:
ps: searching around for this mostly turns up ideas for rolling-your-own connection pool with ThreadLocal() ... am not interested in that ... am sticking with tomcat dbcp.
Joined: May 06, 2005
Concurrency guru Brian Goetz thinks the ThreadLocal is a good choice for implementing per-thread-singletons, which would make for a DAO that neither clutters up the heap with per-request-objects, wastes time creating them, nor wastes time serializing requests across the bottleneck of synchronization contention.
Regarding how many blocked-waiting requests it takes to get the webapp onto its knees, Brian offers that the penalty for uncontended synchronization is somewhere between 10 percent and 200 percent in most cases, but that a contended synchronization may be 50 times slower than an uncontended one.
So for those five simultaneous webapp users, a single synchronized block of code might slow the last guy in by a factor of 500 or so (2*50*5), such that after about 10ms or so in the block, the pain neurons will doubtless begin to fire.
Joined: May 06, 2005
A private messager has pointed out that eliminating shared instance variables eliminates the need for synchronization in order to achieve thread-safety.
I had started down this multi-threaded JDBC performance-enhancement path of inquiry with the assumption that a singleton DAO is best, in order to eliminate time wasted in per-request DAO object creation. Such an approach requires a shared instance variable for the DAO's DataSource.
The DataSource was the object i initially thought required guarded access: What if thread 'a' suspends after getting the Connection reference, and then along comes thread 'b', and gets the same one?
But Brian Goetz claims, in the section "Interpreting Vague Documentation" (Java Concurrency in Practice) that while the JDBC specification doesn't guarantee a thread-safe implementation of DataSource.getConnection(), "it would be absurd if it weren't", and so doesn't require additional client-side locking.
According to that, then, if the reference to the returned Connection is only available on the stack, then mr. private messager is correct, and no synchronized access, much less ThreadLocal binding, is required for a thread-safe DAO singleton.