簡體   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