is reference counting good design
We are working on an application container that uses reference counting as the mechanism to keep track of the requests received and responses sent. The reference count is used in allowing the graceful shutdown of the container, i.e. if (refCount == 0) shutdown;
The reference count is incremented for every Request and also for a pending Response. The reference count is decremented only once an application has accepted a request and also only once the application has sent a valid response.
So here's my question, Is reference counting开发者_如何转开发 a good design decision in this scenario, say as compared to keeping a RequestContext
which is only closed when the Application/Container has sent a response?
Since the software is implemented in Java I was looking at other options in Java and came across this article, http://weblogs.java.net/blog/2006/05/04/understanding-weak-references which made me think that trying to leverage the ReferenceQueue
could be another approach for doing this.
It is actually a really neat way of doing it. You should also additionally use a ThreadLocal (If your request - response pipeline is going to be handled by a single thread)
Basically, when you receive the request. Set a ThreadLocal with a WeakRefernce to your request object (or some attribute of the request, such as user id etc.). Then you can get()
the object anywhere within your processing pipeline.
If You are using a ThreadPool of workers to handle the Request, make sure you unset the Weak Reference object from your thread's ThreadLocal so that no more references of that object exist. If you are spawning a new thread for each request, you dont even need to do that. When the thread dies, the object will automatically be returned to referenceQueue (since no live reference points to that object)
Note that you will pay for that counter with performance hits. Effectively you are requiring a memory barrier for each and every request IFF you are using concurrent threads to service the requests. (A memory barrier instruction typically costs up to ~200 instructions.)
Per your question, it further seems you don't even want a counter but rather a binary flag that indicates if there are any active requests e.g. a requestsInProgress
flag. The idea being that you 'gracefully shutdown' when the flag value is false
.
If your container primarily exposes network endpoints e.g. REST/HTTP then I strongly suggest you consider NIO and employ a single threaded dispatch mechanism to linearize the req/rep at container periphery. (You can queue these and fan out to N processing threads using concurrent queues in java.util.concurrent
.
[NIO subsystem] <-{poll}-[Selector(accept/read)/dispatch thread] => [Q:producer/consumer pattern 1:N]
[NIO subystem] <-{poll}-[Selector(write)/responder thread] <= [Q:producer/consumer N:1]
Benefit?
If you use the same thread for dispatch and responder then no memory barriers are involved -- the thread will be pinned to a core and your flag will be exclusive to its cache line:
e.g.
after dispatch queues request: increment req_in_progress
after responder dequeues response: decrement req_in_progress
There will see be a need for shared memory synchronization on shutdown, but that is far better than incurring that cost per each and every request, as you only pay for it when you actually need it.
If performance is not an issue at all, then why not just use an AtomicInteger
for the counter and put it in the global context?
精彩评论