以下是我的.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();
}
}
}
该计划的目标是:
该类中使用了六个静态全局变量。
在访问之前我应该锁定其中的哪些(我认为词典不需要锁定)?
我应该锁定哪一部分代码?我应该分别锁定开关盒,还是应该将整个while循环锁定在static void ReadFromClient(ClientClass client)
中?
答案 0 :(得分:2)
我们可以肯定地说 ,您应该同步两个字典的访问-因为没有记录表明对字典的操作是线程安全的,并且您正在将它们从多个线程中进行变异。一些类似的结构 do 具有线程安全说明,但没有Dictionary<TKey,TValue>
。
是否需要同步字符串很棘手,尤其是因为您没有显示用法。对引用类型(string
)的读写是原子的,字符串本身是不可变的(至少在正常使用时)。但是,如果您要执行多个操作,而它们之间的值保持不变,则可能需要在 composite 操作期间进行同步。此外,请记住,您不能只lock (stValue)
,因为当stValue
更改时,两个不同的路径将锁定不同的对象。相反,您需要一个单独的字段,该字段仅用于锁定,并且与值无关。
最后,请注意,static
字段-像这样可变时,通常是个坏主意。