I have a stand-alone JMS app that subscribes to several different JMS topics. Each topic has its own session and onMessage() listener. Each onMessage() method updates a common current value table - all the onMessage() methods update the same current value table.
I've read that the onMessage method is actually called on the JMS provider's thread. So, my question is: if all these onMessage() methods are called on a separate thread than my app, doesn't this present a concurrency problem since all these threads update a common CVT? Seems like I need to synchronize access to the CVT somehow?
Short answer to your question: YES, you need to take care of concurrency concerns when your JMS code is updating some common in-memory object.
However, I'm not sure what you mean by "common current value table"? If this is some database table, then database should take care of concurrency issues for you.
EDIT: it turned out that "common current value table" is a common in-memory object. As I mentioned earlier, in this case you need to handle the concurrency concerns yourself (Java concurrency tutorial).
There are mainly two approaches to this problem:
synchronization - suitable if you have low-contention or you are stuck with some non-threadsafe object, then your best choice is synchronization.
high-level concurrency objects that come with the JDK - best fit if you have high-contention and you are using some class from regular collections; just swap in an instance of concurrent collections.
In any case, it is highly recommended to do your own testing to choose the best approach for you.
If you would be dealing with expensive to create non-threadsafe stateless procedural code (no storage of data involved) then you could also use object pooling (e.g. Commons Pool), but this is not relevant in your current issue.
JMS onMessage() method is always called by the JMS provider's thread (also known as asynchronous calling).
Related
I thought finding this answer would be easy...but not so much.
Does anyone know if the OracleDataSource.getConnection method is thread safe?
I do not mean the Connection objects it returns, but the calling of getConnection itself.
Specifically, this method: http://download.oracle.com/otn_hosted_doc/jdeveloper/905/jdbc-javadoc/oracle/jdbc/pool/OracleDataSource.html#getConnection()
The docs and class doesn't say explicitly but, being as how its a connection pool, I'm inclined to believe it is.
This is a problem discussed in Java Concurrency in Practice (Brian Goetz):
4.5.1. Interpreting Vague Documentation
Many Java technology specifications are silent, or at least unforthcoming, about thread safety guarantees and requirements for interfaces such as ServletContext, HttpSession, or DataSource.
...information about servlets...
One can make a similar inference about the JDBCDataSource interface, which represents a pool of reusable database connections. A DataSource provides service to an application, and it doesn't make much sense in the context of a
single threaded application. It is hard to imagine a use case that doesn't involve calling getConnection from multiple threads. And, as with servlets, the examples in the JDBC specification do not suggest the need for any client side locking in the many code examples using DataSource. So, even though the specification doesn't promise that DataSource is thread-safe or require container vendors to provide a thread-safe implementation, by the same "it would be absurd if it
weren't" argument, we have no choice but to assume that DataSource.getConnection does not require additional client-side locking.
...
The spec for JMS sessions warns that Session objects/instances must only be used on the thread in which they are created when there are MessageListener instances registered to a Session. However, it doesn't say anything about being thread-un-safe, or perhaps more accurately, "thread-bound", when using MessageConsumer objects (only).
http://docs.oracle.com/javaee/1.3/api/javax/jms/Session.html
(by "thread-bound", I mean that the object must only be used, ever, on a specific thread, not just that it's unsafe to use it on multiple threads without synchronization or other coordination)
The answer to this question also suggests that Sessions are thread-bound: Relationship between JMS connections, sessions, and producers/consumers
However, there may or may not be some assumptions the author is making, and the question is also more about writing messages than about reading them.
Does anybody know if you can read a message in a Session on one thread, and then have another thread deal with the message and do a commit/rollback for the message (with the session) on that other thread? Only commit (or rollback) would be called against the Session from within the processing thread -- no other calls would be made to the Connection / Session / MessageConsumer / Message chain. Also, the Session would not be used to read again until after the commit/rollback occurred.
The following S/O questions seem closely related, but do no satisfactorily address what I am proposing:
How to continuously read JMS Messages in a thread and achnowledge them based on their JMSMessageID in another thread?
Reason for a JMS Session object to be used in a single threaded context
While I would like to use a Session on multiple threads, there will never be overlapping message requests/transactions.
I'm trying to avoid further refactoring of existing code, so I'm considering doing something a little odd, rather than having a Session on each worker thread.
edit (July 26) - - -
This question, Using a JMS Session from different threads, seems to suggest that it is OK to do synchronized operations with a session on different threads, but I am uncertain which version of the spec is referenced.
Maybe you have found a way in the specification.
A quote from the doc of Sessionhttp://docs.oracle.com/javaee/1.3/api/javax/jms/Session.html
A Session object is a single-threaded context for producing and consuming messages. Although it may allocate provider resources outside the Java virtual machine (JVM), it is considered a lightweight JMS object.
So it's single-threaded; and it's not expensive to create one.
And you have to pay attention to
The close method is the only session method that can be called while some other session method is being executed in another thread.
So you have to make sure that read and commit do not overlap, for example.
From a technical point of view I would refactor it; the code will be easier to read/maintain. Resource handling (open/close) would be in one thread (one method) only. This would simplify exception handling as well.
[From a legal point of view: You admit that you are doing something "odd" - against the recommendation. I would not deliver such a piece of software.]
In this nice article on JMS, Bruce Snyder (Author of "ActiveMQ in Action") mentions:
[one] of the options for implementing a message listener to be used with the Spring DMLC is using javax.jms.MessageListener - It is a standardized interface from the JMS spec but handling threading is up to you.
He doesnt talk about threading in the other two options: Spring SessionAwareMessageListener and MessageListenerAdapter.
My question is: What additional threading concerns are to be addressed with the use of the plain javax.jms.MessageListener, compared to the other two approaches ?
I am thinking that regardless of what option I choose from the above 3, if my listener will be receiving messages on multiple threads, my listener implementation has to be thread-safe.
I went through the examples Bruce had created in github for all the three options.
I didnt see any specific handling for threads in any case.
The xmls of simple and session-aware consumers are almost the same.
As long as your not keeping any state in your MessageListener implementations(through say an instance variable), you don't have to worry about thread-safety with any of the three approaches. If you are keeping state, then like in any multi-threading scenario, you will have to take care of how you synchronize access to the state.
I am also thinking of integrating the disruptor pattern in our application. I am a bit unsure about a few things before I start using the disruptor
I have 3 producers, mainly a FIX thread which de-serialises the requests. Another thread which continously modifies order price as the market moves. Also we have one more thread which is responsible for de-serialising the requests sent from a GUI application. All three threads currently write to a Blocking Queue (hence we see a lot of contention on the queue)
The disruptor talks about a Single writer principle and from what I have read that approach scales the best. Is there any way we could make the above three threads obey the single writer principle?
Also in a typical request/response application, specially in our case we have contention on an in memory cache, as we need to lock the cache when we update the cache with the response, whilst a request might be happening for the same order. How do we handle this through the disruptor, i.e. how do I tie up a response to a particular request? Can I eliminate the lock on the cache if yes how?
Any suggestions/pointers would be highly appreciated. We are currently using Java 1.6
I'm new to distruptor and am trying to understand as much usecases as possible. I have tried to answer your questions.
Yes, Disruptor can be used to sequence calls from multiple
producers. I understand that all 3 threads try to update the state
of a shared object. And a single consumer which takes necessary action on the shared object. Internally you can have the single consumer delegate calls to the appropriate single threaded handler based on responsibility. The
The Disruptor exactly does this. It sequences the calls such that
the state is accessed only by a thread at a time. If there's a specific order in which the event handlers are to be invoked, set up the memory barrier. The latest version of Disruptor has a DSL that lets you setup the order easily.
The Cache can be abstracted and accessed through the Disruptor. At a time, only a
Reader or a Writer would get access to the cache, since all calls to
the cache are sequential.
Suppose that I have a method called doSomething() and I want to use this method in a multithreaded application (each servlet inherits from HttpServlet).I'm wondering if it is possible that a race condition will occur in the following cases:
doSomething() is not staic method and it writes values to a database.
doSomething() is static method but it does not write values to a database.
what I have noticed that many methods in my application may lead to a race condition or dirty read/write. for example , I have a Poll System , and for each voting operation, a certain method will change a single cell value for that poll as the following:
[poll_id | poll_data ]
[1 | {choice_1 : 10, choice_2 : 20}]
will the JSP/Servlets app solve these issues by itself, or I have to solve all that by myself?
Thanks..
It depends on how doSomething() is implemented and what it actually does. I assume writing to the database uses JDBC connections, which are not threadsafe. The preferred way of doing that would be to create ThreadLocal JDBC connections.
As for the second case, it depends on what is going on in the method. If it doesn't access any shared, mutable state then there isn't a problem. If it does, you probably will need to lock appropriately, which may involve adding locks to every other access to those variables.
(Be aware that just marking these methods as synchronized does not fix any concurrency bugs. If doSomething() incremented a value on a shared object, then all accesses to that variable need to be synchronized since i++ is not an atomic operation. If it is something as simple as incrementing a counter, you could use AtomicInteger.incrementAndGet().)
The Servlet API certainly does not magically make concurrency a non-issue for you.
When writing to a database, it depends on the concurrency strategy in your persistence layer. Pessimistic locking, optimistic locking, last-in-wins? There's way more going on when you 'write to a database' that you need to decide how you're going to handle. What is it you want to have happen when two people click the button at the same time?
Making doSomething static doesn't seem to have too much bearing on the issue. What's happening in there is the relevant part. Is it modifying static variables? Then yes, there could be race conditions.
The servlet api will not do anything for you to make your concurrency problems disappear. Things like using the synchronized keyword on your servlets are a bad idea because you are basically forcing your threads to be processed one at a time and it ruins your ability to respond quickly to multiple users.
If you use Spring or EJB3, either one will provide threadlocal database connections and the ability to specify transactions. You should definitely check out one of those.
Case 1, your servlet uses some code that accesses a database. Databases have locking mechanisms that you should exploit. Two important reasons for this: the database itself might be used from other applications that read and write that data, it's not enough for your app to deal with contending with itself. And: your own application may be deployed to a scaled, clustered web container, where multiple copies of your code are executing on separate machines.
So, there are many standard patterns for dealing with locks in databases, you may need to read up on Pessimistic and Optimistic Locking.
The servlet API and JBC connection pooling gives you some helpful guarantees so that you can write your servlet code without using Java synchronisation provided your variables are in method scope, in concept you have
Start transaction (perhaps implicit, perhaps on entry to an ejb)
Get connection to DB ( Gets you a connection from pool, associated with your tran)
read/write/update code
Close connection (actually keeps it for your thread until your transaction commits)
Commit (again maybe implictly)
So your only real issue is dealing with any contentions in the DB. All of the above tends to be done rather more nicely using things such as JPA these days, but under the covers thats more or less what's happening.
Case 2: static method, this presumably implies that you now keep everything in a memory structure. This (barring remote invocation of some sort) impies a single JVM and you managing your own locking. Should your JVM or machine crash I guess you lose your data. If you care about your data then using a DB is probably better.
OR, how about a completely other approach: servlet simply records the "vote" by writing a message to a persistent JMS queue. Have some other processes pick up the votes from the queue and adds them up. You won't give immediate feedback to the voter this way, but you decouple the user's experience from the actual (in similar scenarios) quite complex processing .
I thing that the best solution for your problem is to use something like "synchronized" keyword and wait/notify!