繁体   English   中英

Java中有多个线程访问同一方法时的线程安全

[英]Thread safety when multiple threads accessing the same method in Java

我有这样的方法

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

    store(key, data);
}

如果多个线程同时调用此方法,是否将在多个线程之间共享数据值?

就像线程A通过handleString(objFromThreadA)调用此方法一样,线程B通过handleString(objFromThreadB)调用此方法。 会不会有那的价值任何机会String data在线程A被替换的值String data的线程B?

-----编辑1 -----

我对这里的线程安全有些困惑。 下面的方法是来自我用于MQTT客户端的库的回调。

/**
     * 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;

每次调用此方法。 我创建了一个新线程来处理message对象,这就是我从message对象中获取了大量数据和键。 当我阅读评论时,它说此方法是同步调用的,那么这是否意味着消息一定是线程安全的?

这是我处理消息对象的方式。

@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);
}

在handleMessage(String topic,String message)中,我有这样的东西:

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

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

因此,我不确定在这里执行的操作是否线程安全。 如果我将新分配的String( new String(message.getPayload()) )传递给handleMessage方法,这是否意味着将新String放在一个线程的堆栈上,并且其他任何线程都不能共享该字符串?

每个方法调用都是其自身范围内的方法。

您不需要线程使其可见-只需使用递归方法即可使这一点变得清晰:

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

在第4行中,调用了该方法的新实例,并且s现在是外部s的截断版本。 但是在完成内部调用之后,外部s根本不受影响。

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

对于线程,可能的冲突(更好的是:不可能的冲突)只会更难以显示。

但是问题是合法的。 乍一看,等效代码在bash中的表现如何(对我而言,非常令人惊讶):

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 >

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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