3

I have a fixed number n of identical resources that need to be shared between n or more threads. Whenever a thread needs to use a resource, it can take any available one, for which it runs an indetermininate amount of time (i.e. usage times are not uniform) and then release it.

What is a good Java data structure to manage this scenario? I can only think of one way to do it, which is by using a LinkedBlockingQueue and the take and put operations as locking and releasing a resource, respectively. I'd just like a suggestion from the concurrency experts:

For those who are curious: The resources that need to be shared are identical copies of a non-reentrant FORTRAN library for computing multivariate normal CDFs and moments. Spectacular numerical library, but written in an age where thread-safe code wasn't something to be worried about. In this case we make n copies of the library, where n = Runtime.getRuntime().availableProcessors() .

EDIT: I don't want to create the overhead of threads to execute this library. It is already being called from multiple threads; the calling threads should just be able to lock a resource and get on with it.

UPDATE: See https://stackoverflow.com/a/19039878/586086 for the motivation and the implementation.

Community
  • 1
  • 1
Andrew Mao
  • 35,740
  • 23
  • 143
  • 224
  • 1
    You can just create N tasks to add to a fixed size thread pool. – Peter Lawrey Sep 26 '13 at 15:03
  • @PeterLawrey In my case I want the tasks to run synchronously from the perspective of the threads starting them. What benefit would I get by passing the jobs to different threads? – Andrew Mao Sep 26 '13 at 15:12
  • By "synchronously" you mean one after another? In that case you only need one thread. The benefit of using multiple threads is they might be performed concurrently and thus take less time. – Peter Lawrey Sep 26 '13 at 15:28
  • @PeterLawrey sorry, I mean that the thread should block until the result is computed. I don't see why there would be a need to instantiate more threads in a pool, because the calling thread actually enters the native library. – Andrew Mao Sep 26 '13 at 15:31
  • Threads are always busy until finished. Once you have a pool of threads you wouldn't create more. Can you clarify what your doubt is? – Peter Lawrey Sep 26 '13 at 15:35
  • @PeterLawrey I am trying to make a non-reentrant library reentrant by making copies of it and having the calling threads take a lock on a unique copy before executing native code. There is no need to start a threadpool for this. I'm asking for a recommendation on using stuff like `LinkedBlockingQueue`, `Semaphore`, etc – Andrew Mao Sep 26 '13 at 17:22
  • So you want a pool of library resources you can use single threaded. You can use an ArrayDeque or a linkedBlockingQueue as you suggest. A simpler approach is to give each thread a thread local copy. This avoids the overhead of allocating and freeing – Peter Lawrey Sep 26 '13 at 18:13
  • @PeterLawrey what am I allocating and freeing? Since I need to make actual physical copies of the file library beforehand, how do you suggest giving each thread a thread-local copy if I don't know how many threads are going to be calling the library? Using a constant equal to the number of CPUs seems to make more sense. Also `ArrayDeque` does not block, are you talking about `ArrayBlockingQueue`? – Andrew Mao Sep 26 '13 at 18:16
  • I guess I don't understand your limitations as no one would design a system to work this way. I wouldn't block but instead create a new one as required. If you have to preallocate you risk doing too many or too little. In this case you need a blocking queue as there is nothing else you can do if you dont have enough resources. – Peter Lawrey Sep 26 '13 at 18:27
  • @PeterLawrey yes, you wait for a resource to free up...but why would it matter if you can get it earlier if all CPU cores are being used anyway? – Andrew Mao Sep 26 '13 at 18:35
  • You can have threads which are not running which have not freed a resource. – Peter Lawrey Sep 26 '13 at 18:38
  • @PeterLawrey I don't understand what's so difficult to comprehend about this. The following link is basically what I need to do; do you have any suggestions? https://github.com/mizzao/libmao/blob/master/src/main/java/net/andrewmao/misc/LibraryReplicator.java – Andrew Mao Sep 26 '13 at 18:50
  • 1
    The part which is difficult to comprehend is what is stopping you from doing it already. That is why I am trying to guess what is holding you back. – Peter Lawrey Sep 26 '13 at 19:10
  • @PeterLawrey I did it already; that is my repo. I'm asking you if you have any suggestions based on my implementation. – Andrew Mao Sep 26 '13 at 19:58
  • It appears you are limited entirely by the library you have to work around. To improve it you need to fix the use of the library. – Peter Lawrey Sep 26 '13 at 20:02

2 Answers2

1

The pattern you're describing is a resource pool. A thread-safe queue is a reasonable way to handle the situation when the resources are fairly simple, though you might also consider a pool library such as pool4j.

chrylis -cautiouslyoptimistic-
  • 75,269
  • 21
  • 115
  • 152
  • Any other suggestions than a thread-safe queue? Pointers to any Java concurrent classes in particular? – Andrew Mao Sep 26 '13 at 17:23
  • You already identified the `BlockingQueue` interface. Given that you have a fixed number of library instances that won't change over the lifetime of the program, `ArrayBlockingQueue` might be a bit better than `LinkedBlockingQueue`, but you've been on the right track. – chrylis -cautiouslyoptimistic- Sep 26 '13 at 23:36
0

Create a singleton class with a list of fixed resource, and associated flag to mark each resource as available or unavailable, and 2 synchronized methods, something like:

synchronized Resource getResource(){
   find an unavailable resource, mark it as unavailable and return it
}

synchronized int returnResource(Resource r){
   find the matching resource on list and mark it as available.
}
Alexander Vogt
  • 17,879
  • 13
  • 52
  • 68
Don Ha
  • 689
  • 5
  • 9