[英]Which part of the source code should I lock?
以下是.net服務器的基本框架:
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();
}
}
}
該計划的目標是:
該類中使用了六個靜態全局變量。
在訪問之前應該鎖定其中的哪一個(我認為詞典不需要鎖定)?
我應該鎖定哪一部分代碼? 我應該分別鎖定開關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.