views:

195

answers:

4

Hi,

There is a JDK function that, although the javadocs does not declare it as thread-safe, from looking at the code in Google, it seems that I could get the result I want by calling it from multiple threads without undesirable side-effects, since the function uses mainly stack variables. So it does not matter if it has synchronized blocks. I am wondering though if I am missing something and eventually run into trouble. The function is connection.call(requestMsg, url); of SOAPConnection from SAAJ api. Any pointer on how I should analyze this in order to decide to use it from multiple threads or not?

Thanks!

A: 

The general rule is that methods And classes are thread-safe unless stated to the contrary. So for example RMI methods are thread-safe, ditto this one.

EJP
Thank you for the reply. I thought it was the opposite. That jdk classes are not thread safe unless stated otherwise. So you are saying I can safely call the function from multiple threads since there is nothing stated in javadocs about thread-safety?
@EJP: Do you have a reference for this "general rule"? I would definitely not assume a call is thread safe just because the docs don't specifically say it isn't.
Ash
See Stephen C's answer above. Downvoter please note.
EJP
@EJP - but also note that my answer also says that Sun **plainly** states that their own javadocs do not follow that rule. IMO, that makes your answer is poor advice for someone trying to figure out thread-safety issues, and the downvote is not unreasonable.
Stephen C
I was quoted the same rule by a senior Sun engineer when I asked about the thread safety of RMI stubs in about 1999. In general all these connection-oriented things are thread-safe because the connections themselves are. I don't see anything here that says the API mentioned by the OP isn't thread-safe.
EJP
+1  A: 

The following quote comes from "How to Write Doc Comments for the Javadoc Tool"

The Java Platform API Specification is a contract between callers and implementations.

The Specification describes all aspects of the behavior of each method on which a caller can rely. It does not describe implementation details, such as whether the method is native or synchronized. The specification should describe (textually) the thread-safety guarantees provided by a given object. In the absence of explicit indication to the contrary, all objects are assumed to be "thread-safe" (i.e., it is permissible for multiple threads to access them concurrently). It is recognized that current specifications don't always live up to this ideal.

To me this says, that you ideally should be able to assume that the standard Java APIs are thread-safe unless it is stated otherwise. But the last sentence says to me that this is a rather dangerous thing to assume that this is always true. Certainly, for most of Swing APIs you should NOT assume thread-safety.

I think that the following is a reasonable approach to deciding what you can rely on to be thread-safe:

  • If the javadoc explicitly says something is thread-safe, you can rely on it being thread-safe going forward.
  • If the javadoc explicitly says something is not thread-safe, you can rely on it being non-thread-safe going forward.
  • If the javadoc says nothing, AND a careful examination of the source code tells you that it is thread-safe, you can rely on it being thread-safe going forward.
  • If the javadoc says nothing, AND a careful examination of the source code tells you that it is not thread-safe, all bets are off. It could be a javadoc error, or a shortcoming of the current implementation.

(This is based on the observation that Sun / Oracle are unlikely to make changes that break backwards compatibility. Changing thread-safety characteristics of standard APIs could cause of insidious concurrency bugs ... and is therefore doubly unlikely.)

Stephen C
I strongly advise against that. The recommendation is very outdated.
irreputable
@irrefutable - which part of "that" do you recommend against, and why?
Stephen C
+1  A: 

I am with Stephen - If it does not explicitly say that it is Thread Safe, assume it is not.
That being said, I looked through the code and it looks OK after about a 15 minute inspection.

The main thing is to see if there are any shared variables between threads and if they would be affected by being called by two or more threads concurrently. Of course this can be a lengthy and tricky process, since a class may be composed of several other classes, which in turn are composed of several others.

If it were me, I would restructure my code to make sure that I did not call in a multithreaded way, since debugging this would be a nightmare and I have no guarantees that it will work 100% of the time.

It is your call: As Dirty Harry once said: "Do you feel lucky today ?, well do you ?"

On another note, I answered this question and the answer may also apply to this.

Romain Hippeau
@Romain: "If it were me, I would restructure my code to make sure that I did not call in a multithreaded way"Actually I would like to call it in a multithreaded way since it seems to suit exactly what I want to do. I.e. my aim is to call this function through several threads concurrently, and the result I expect is that each thread will send its message through a different HTTP connection. The code seemed to me OK also but my worry is if I missed something. Is there any particular tips on code inspection for an issue like mine? Otherwise I would have to find another approach for my messaging.
@user384706 All I am trying to say is that it looks like it may work on inspection, just not 100%. The only thing you can look at is the code and making sure there not any Thread unsafe shared variables. It would be so much easier if we could assume it was OK unless documented.
Romain Hippeau
+2  A: 

Hell No. If it's not specifically documented as thread safe, we shall not assume that. Don't mind Sun's recommendation written in the days of Vector, Hashtable, StringBuffer, old java memory model and single processor machines. The fashion has turned. We are living in a dramatically different world of java concurrency.

For a mutable class, it's far more likely that it's written with one thread in mind. So I would argue that without doc we'll have to assume it's for single thread. External synchronization must be used in a bigger picture of things. (That usually helps performance compared to locking at finer level).

For a class that's actually designed to be used in multiple threads, it must provide painstakingly detailed document of how it behaves. It is nonsense to mark it as simply "thread safe". There are too many things to explain and document, check out any concurrency class.

Therefore, it is nonsense to assume a "default" thread safety mode. It doesn't mean anything.

--

For you specific query, if the implementation is like this

constructor()
  open socket

Response call(Request)
  write request to socket output stream
  read response from socket input stream

close()
  close socket

Without synchronization on call(), this is obviously UNSAFE. If you have concurrent reads/writes on a TCP connection, chaos assured.

Suppose I wrote a safer implementation, would I keep silent? Of course not. I'll tell the user that concurrent call()s are allowed; each request is written atomically; pipeline is used for throughput; responses are returned in the order of requests; close() can be invoked anytime by any thread; outstanding calls will have x seconds to finish gracefully; after that the connection is aborted; any thread waiting on call() will receive an excpetion.

irreputable
@irreputable: Call has a local HttpUrlConnection object declared, so each thread will use a separate instance in its stack. I understand what you are saying, but if concurrent calls from separate threads, wreck an api, isn't it logical to expect this to be explicitely documented? Do you have a concrete example why the reference to SUN docs should not be taken seriously? Because the answers of Romain and Stephen make sense to me. After all my question is targeting a specific api method. It is not a generic question on multithreading.
if you want to tie your safety to implementation details of another library, you are free to do so. let me ask you though, if the connection is stateless, what's the point of sharing it among threads? it's so cheap you can create a dime a million.
irreputable
@irreputable: I do not want to share the connection among threads. I want each thread to send the message through a different http connection. Since call has a local HttpUrlConnection object, it seems I will get the desired result. My concern was if I can do it without undesirable side-effects. Your comment "if you want to tie your safety to implementation details of another library" makes a lot of sense in a general manner. Specifically for the jdk though, why do you feel that even jdk is not reliable to a problem like mine?
if *SOAPConnection* is stateless and costs nothing to create, why do you want to share it at the risk of being wrong?
irreputable
+1. This answer also applies to [one of my questions](http://stackoverflow.com/questions/2857332/safe-to-update-separate-regions-of-a-bufferedimage-in-separate-threads)
finnw