簡體   English   中英

我應該鎖定源代碼的哪一部分?

[英]Which part of the source code should I lock?

以下是.net服務器的基本框架:

C#服務器框架

class ServerProgram
{
    static string origClientID = string.Empty;
    static string reqClientID = string.Empty;
    static string stKey = string.Empty;
    static string stValue = string.Empty;
    static Dictionary<string, KeyValue> KeyValueDictionary;
    static Dictionary<string, ClientClass> ClientDictionary;

    static void Main(string[] args)
    {
        Console.Title = "Server";
        Console.WriteLine("Server program started on address [" + Constants.SERVER_IP +":"+Constants.PORT_NO+"]");

        KeyValueDictionary = new Dictionary<string, KeyValue>();
        ClientDictionary = new Dictionary<string, ClientClass>();

        string ipAddress = Constants.SERVER_IP;
        int portNo = Constants.PORT_NO;

        IPAddress ip = IPAddress.Parse(ipAddress);            
        TcpListener listener = new TcpListener(ip, portNo);            

        // poll for clients in a 2nd thread
        Thread thread = new Thread(delegate()
        {
            ServerProgram.PollIncomingClientConns(listener);
        });

        thread.Start();
    }

    #region catching client connections
    static void PollIncomingClientConns(TcpListener listener)
    {
        listener.Start();

        try
        {
            bool keepRunning = true;

            while (keepRunning)
            {
                ClientClass client = new ClientClass(listener);

                ClientDictionary.Add(client.ID, client);

                Thread thread = new Thread(delegate()
                {
                    ServerProgram.ReadFromClient(client);
                });
                thread.Start();
            }
        }
        catch (Exception ex)
        {
            var inner = ex.InnerException as SocketException;
            if (inner != null && inner.SocketErrorCode == SocketError.ConnectionReset)
                Console.WriteLine("Disconnected");
            else
                Console.WriteLine(ex.Message);

            listener.Stop();
        }
    } 
    #endregion     

    static void ReadFromClient(ClientClass client)
    {
       try
        {
            while (client.Tcp.Connected)
            {
                string str = client.Read();
                Console.WriteLine("[" + client.ID + "] says: " + str);

                switch(str)
                {
                    case Commands.AddKeyValue:
                        //...                        
                        break;

                    case Commands.ListKeys:
                        //...
                        break;

                    case Commands.UpdateValue: 
                        //...
                        break;

                    case Commands.Yes:                            
                        //...
                        break;
                }
            }
        }
        catch
        {
            client.Disconnect();
        }
    }
}

該計划的目標是:

  1. 服務器保留一個通用的鍵值字典。
  2. 客戶端能夠添加,更新和查看服務器中的鍵值。

該類中使用了六個靜態全局變量。

在訪問之前應該鎖定其中的哪一個(我認為詞典不需要鎖定)?

我應該鎖定哪一部分代碼? 我應該分別鎖定開關static void ReadFromClient(ClientClass client) ,還是應該在static void ReadFromClient(ClientClass client)鎖定整個while循環?

我們可以肯定地說,您應該同步兩個字典的訪問-因為沒有任何關於字典的操作被證明是線程安全的,並且您正在將它們從多個線程中進行變異。 一些類似的結構確實具有線程安全性說明,但沒有Dictionary<TKey,TValue>

是否需要同步字符串是很棘手的,尤其是因為您沒有顯示用法。 對引用類型( string )的讀寫是原子的,並且字符串本身是不可變的(至少在正常使用時)。 但是,如果您要執行多個操作,而它們之間的值將保持不變,則可能需要在復合操作期間進行同步。 此外,請記住,您不能只lock (stValue) ,因為當stValue更改時,兩個不同的路徑將針對不同的對象鎖定。 相反,您需要一個單獨的字段,該字段僅用於lock ,並且與值無關。

最后,請注意,像這樣可變的static字段通常不是一個好主意。

暫無
暫無

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

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