簡體   English   中英

在Java線程中同步

[英]Synchronized in a Java thread

我的程序是連接到多個服務器的客戶端。 我將連接對象保存到靜態映射對象中的所有服務器:

服務器1->連接1
服務器2->連接2
serverN-> connectionN

public class CacheConnection {

    private final static Map cacheConnection = new HashMap();

    public static void add(String serverName, Socket sock) {
        synchronized (cacheConnection) {
            cacheConnection.put(serverName, sock);
        }
    }

    public static Socket get(String serverName) {
        return (Socket) cacheConnection.get(serverName);
    }

    ..
}

我有許多線程從此映射獲取連接以與服務器通信。 如何確保一個連接一次只能由一個線程使用?

例如,我想確保線程1和線程2不能同時使用連接1。

我不確定您想要什么。 我假設您要保證一次僅一個線程訪問一台特定服務器。

如果您的連接就像一個套接字,那么您可以將其用作同步語句中的鎖:

private void send(Connection c, Data d) {
  synchronized (c) {
    // for each connection object, only one thread may be inside this block.
    // all other threads wait until the thread currently in this block exits it.
    c.send(d);
  }
}

// somewhere else ...

Data data = determineDataToSend()
Connection connection = map.get(key);
send(connection, data)

您也可以將邏輯放入連接的裝飾器中。 如果您的連接具有多個發送或接收方法(例如,因為您使用的是RMI等更高的抽象級別),則此功能特別有用:

public interface PowerfulConnection {
  public void doA();
  public int doB(ParameterForB param);
}

public class ConnectionImpl implements PowerfulConnection {
   // handles the actual connection
}

/**
 * This method is a decorator for PowerfulConnection that synchronizes all method accesses.
 */
public class SynchronizedConnection implements PowerfulConnection {
  private PowerfulConnection target;

  public SynchronizedConnection(PowerfulConnection target) {
    if (target == null) throw new NullPointerException();
    this.target = target;
  }

  public synchronized void doA() {
    target.doA();
  }

  public synchronized int doB(ParameterForB param) {
    return target.doB(param);
  }
}

如果您使用裝飾器方法,則唯一需要更改的就是實例創建。 代替:

private void connect(key, connectionParams) {
  map.put(key, new ConnectionImpl(connectionParams));
}

采用

private void connect(key, connectionParams) {
  map.put(key, new SynchronizedConnection(new ConnectionImpl(connectionParams)));
}

或者,在您的第一個示例中,get方法可能只是從地圖上刪除了連接。 當然,這意味着客戶端必須確定(可能在finally塊中,完成后再次調用add)

然后,等待並通知循環,以了解何時有客戶端進入以請求連接,但該連接不存在。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM