简体   繁体   中英

Thread safety when multiple threads accessing the same method in Java

I have a method like this

private handleObj(Obj obj)
{
    String data = obj.getData;
    String key = obj.getKey;

    store(key, data);
}

If this method is called by multiple threads at the same time, will the value of data be shared across multiple threads?

Like if thread A calls this method by handleString(objFromThreadA) then thread B calls this method by handleString(objFromThreadB). Would there be any chance that value of String data in thread A was replaced by value of String data in thread B?

----- Edit 1 -----

I am a bit confused about thread safety here. The method below is a callback from a lib that I am using for MQTT client.

/**
     * This method is called when a message arrives from the server.
     *
     * <p>
     * This method is invoked synchronously by the MQTT client. An
     * acknowledgment is not sent back to the server until this
     * method returns cleanly.</p>
     * <p>
     * If an implementation of this method throws an <code>Exception</code>, then the
     * client will be shut down.  When the client is next re-connected, any QoS
     * 1 or 2 messages will be redelivered by the server.</p>
     * <p>
     * Any additional messages which arrive while an
     * implementation of this method is running, will build up in memory, and
     * will then back up on the network.</p>
     * <p>
     * If an application needs to persist data, then it
     * should ensure the data is persisted prior to returning from this method, as
     * after returning from this method, the message is considered to have been
     * delivered, and will not be reproducible.</p>
     * <p>
     * It is possible to send a new message within an implementation of this callback
     * (for example, a response to this message), but the implementation must not
     * disconnect the client, as it will be impossible to send an acknowledgment for
     * the message being processed, and a deadlock will occur.</p>
     *
     * @param topic name of the topic on the message was published to
     * @param message the actual message.
     * @throws Exception if a terminal error has occurred, and the client should be
     * shut down.
     */
    public void messageArrived(String topic, MqttMessage message) throws Exception;

Every time this method is called. I create a new thread to handle the message object, which is I am getting a lot of data and keys from message object. As I read the comments, it says that this method is called synchronously, so does that mean message is sure to be thread safe?

Here's how I handle the message object.

@Override
public void messageArrived(String topic, MqttMessage message) throws Exception
{
    Runnable runnable = new Runnable() 
    {   
        @Override
        public void run() 
        {
            try 
            {
                handleMessage(topic, new String(message.getPayload()));
            } 

            catch (Exception e) 
            {
                e.printStackTrace();
            }
        }
    };

    threadPool.execute(runnable);
}

And within handleMessage(String topic, String message) I have something like this:

private void handleMessage(String topic, String message)
{
    JSONObject messageJson = new JSONObject(message);

    //get values from JSON
    String value = messageJson.get("key");
}

So, I am not sure if what I am doing here is thread safe. If I am passing a newly allocated String ( new String(message.getPayload()) ) to my handleMessage method, does that mean the new String is placed on stack of one thread, and no other threads can share that string?

Every method invocation is a method in its own scope.

You don't need threads to make it visible - just use a recursive method, to make this clear:

void middle (String s) {
    println ("<" + s);
    if (s.length () > 2) 
        middle (s.substring (1, s.length () - 1));
    println (s + ">");
}

In line 4, a new instance of the method is called, and s is now a truncated version of the outer s. But on completion of the inner call, the outer s is not affected at all.

-> middle ("foobar")
<foobar
<ooba
<ob
ob>
ooba>
foobar>

With threads, the possible collision (better: impossible collision) is only harder to show.

But the question is legitim. See, how, at first glance, equivalent code, behaves in bash (for me, very surprisingly):

middle () {
  s=$1
  echo "< $s"
  len=${#s}
  if (( $len > 2 ))
  then
      middle ${s:1:((len-2))}
  fi
  echo "$s >"
}

middle "foobar"

< foobar
< ooba
< ob
ob >
ob >
ob >

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM