views:

134

answers:

5

I have a problem with a specific java client library. Here is the situation:

I have made a program that uses the library. The program is a class named 'WorkerThread' that extends Thread. To start it I have made a Main class that only contains a main() function that starts the thread and nothing else. The worker uses the library to perform comm with a server and get results. The problem appears when I want to run 2 WorkerThreads simultaneously. What I first did was to do this in the Main class:

public class Main
{
   public static void main(String args[])
   {
      new WorkerThread().start(); // 1st thread.
      new WorkerThread().start(); // 2nd thread.
   }
} 

When I run this, both threads produce irrational results and what is more , some results that should be received by 1st thread are received by the 2nd instead.

If instead of the above, I just run 2 separate processes of one thread each, then everything works fine.

Also:

1.There is no static class or method used inside WorkerThread that could cause the problem. My application consists of only the worker thread class and contains no static fields or methods
2.The library is supposed to be usable in a multithreaded environment. In my thread I just create a new instance of a library's class and then call methods on it. Nothing more.

My question is this: Without knowing any details of my implementation, is the above situation and facts enough to prove that there is a bug in the library and not in my programm? Is it safe to assume that the library might for example use a static object or an object shared between library created threads that is indirectly shared by my 2 threads and this causes the problem? If no then in what hypothetical situation could the bug originate in the worker class code?

EDIT: I didnt say the library because i want to know if the facts above can produce an answer to my question independently of the library, but anyway the library is rabbit mq java client. Each thread creates 1 connection and 2 channels and uses one to publish data and one to receive results.

EDIT 2: New fact: Problem seems to depend on the rate at which I send stuff to the queues. Sending in slower rate lowers the amount of wrong results.

+1  A: 

I would assume the problem is in the library indeed.

However, I'd go further, check-out the library sources (or use a decompiler) and see (perhaps using a debugger) what is actually happening.

That way you will both prove the problem is not in your code & be able to submit a valuable bug-report.

Bozho
This is what i am doing right now. But I am in a hurry to deliver results and want to know if I should just my code or use another library. After that, since I like the specific system (it is rabbit mq, and the library i am talking about is the java client of it), i will try look at the source
Paralife
A: 

It is hard to guess without knowing what library does. Even if library was designed for usage in multi thread environment, it still might require some additional actions from caller code (i.e. you) to work properly. Imagine that library is a DB driver and your threads do something with the same database. If DB-requests in threads are not properly grouped in transactions with proper isolation level, results might be bad.

However if library is not expected to work with some shared resource, odds that there is something wrong with library are high. In this case it might be good idea to create a minimal test application that proves bad behavior and submit it as bug report to the author of the library.

iPhone beginner
The library is rabbitmq java client. I edited my post to include it.
Paralife
In your example you implicitly assume I share the same connection in my threads. But in my case it is like i first start the thread, and inside it I create connection to the database
Paralife
A: 

From your description I would say that the problem is that the library is opening a single connection to the server and it is not doing anything to multiples access from multiple worker threads. The reason that the one thread per process model works is that the server sees to separate connections and would never think to mix them.

I don't know if you could call this a bug though. Since we don't know more about the library in question. It might be the case that you are responsible for passing in an extra ID that will get returned with each request to figure out the correct target. Or it could be that the library expects you to properly serialize your interactions with it. In that case you need to pick an appropriate place to synchronize you access.

Ukko
That is definitely not the reason because in each thread I open a separate connection explicitly. Also the library is rabbitmq java client. I edited the post to mention it.
Paralife
A: 

Your library might not be unconditionally thread safe but conditionally thread safe. I assume it is pretty hard to figure this out without the required documentation from the library owner/vendor. Your library could be conditionally thread safe which is according to Joshua Block -

Like unconditionally thread-safe, except that some methods require external synchronization for safe concurrent use. Examples include the collections returned by the Collections.synchronized wrappers, whose iterators require external synchronization

Shamik
A: 

Without knowing any details of my implementation, is the above situation and facts enough to prove that there is a bug in the library and not in my programm?

No.

If no then in what hypothetical situation could the bug originate in the worker class code?

A hypothetical situation is when your two threads are publishing and receiving from the same queues/topics, and you have message ordering expectations that neither your program (e.g., via inter-thread coordination) nor the API/library guarantees.

Noel Ang
I dont have message ordering expectations and inter-thread sync is not an issue since:1. Nothing is shared between the threads. 2. Everything works fine when i run the threads each one from different jvm. This at least proves that the thread doesnt need access to anything outside its private space and it doesnt need to sync anything with other threads. The threads ara isolated. Literally, I start the thread by static void main(){ thread.start();}. Everything the thread needs it creates it in its own space. Someone could even argue I dont need threads for this.
Paralife
Also it proves that the reason any message ordering expectations I might have( which i dont ) and dont get fulfilled has nothing to do with sending to the same queue. In the two separate jvm version the processes still send to the same queue, by using private connections each.
Paralife
JVMs take time to start up, and timing sensitivies that present between two threads running in the same JVM may not manifest between two threads executing in separate JVMs. Unless and until we can see the worker code, and you specify what the precise problem is, I can't see arriving at a conclusive answer.
Noel Ang
Do "timing sensitivities" affect threads that share nothing, and how? Or to express it better, since my threads share nothing in my code, but maybe share something in the library code, what you say is just a cause of a manifestation of a bug that lies in the library code.
Paralife
Your threads *are* sharing something: the MQ resource(s) being written to and read from. Sharing concerns extend beyond the language/code.
Noel Ang
Yes but the sharing is not created by my code. It is created in the library. Also these resources (Channels, connections) are separate instances in each thread. If they are not it is the library's fault for providing me a createConnection() that returns a shared instance when it is supposed to return a fresh one. Also, the queues , as resources, are Strings to my code. And Strings are immutable. Finally if those concerns extended beyond the language/code then they should manifest themselves in separate jvm too.
Paralife
The queues are not Strings. The queues are queues. We have a conceptual disconnect here. If you have two threads mutating a queue concurrently, absent inter-thread synchronization, how do you know which thread completed the mutation first? What are your expectations about message ordering that isn't being met by the program that makes you think there's a bug *anywhere*?
Noel Ang
No, the queues are strings. A thread ,using the library in discussion, cannot mutate a queue. The notion of mutating a queue does not exist even conceptually in our context. A queue, even in the library code, is just a name sent through the wire to the server. In fact, in rabbit mq, you cannot send to a queue. You send the data to the server along with a string , which the server uses to decide where to route your data to. Secondly, I have the following expectations about message ordering: None. Anyway I think we should just drop this thread since I am not able to make you see the problem.
Paralife
If you have no expectations about message ordering, then there is no problem. I suggest that you frame your issues with concrete information if you wish to be more productive next time.
Noel Ang
lol... Ok. You are totally right. I agree.
Paralife