myObject A1 = new myObject();
myObject A2 = new myObject();
int i = -1;
myObject[] A = new myObject[2];
private void button1_Click(object sender, EventArgs e)
{
A[0] = A1;
A[1] = A2; System.Threading.Thread t1 = new System.Threading.Thread(Thread1);
System.Threading.Thread t2 = new System.Threading.Thread(Thread1);
t1.Start();
t2.Start();
} private void Thread1()
{
i++;
Console.WriteLine("t" + (i+1) +"线程开始了"); //注意这句代码
lock (A[i].obj)
{
foreach (myObject c in A)
{
c.i++;
}
Console.WriteLine(A[i].i.ToString());
System.Threading.Thread.Sleep(10000);
Console.WriteLine(A[i].i.ToString());
} //Console.WriteLine("t" + (i + 1) + "线程结束了"); }
} public class myObject
{
public int i = 0;
public object obj = new object();
}
请高手看看上面这段代码,为什么把下面这句注销掉和不注销掉,输出的结果不一样?
Console.WriteLine("t" + (i+1) +"线程开始了"); //注意这句代码
我正好做了一个socket通信类库,贴出来一起研究一下。
服务器部分public class Server
{
public byte[] buffers;
Socket[] sockets;
SocketAsyncEventArgs[] sendargs;
SocketAsyncEventArgs[] recvargs;
Queue<int>[] queues;
Object[] objs;
int[] states;
int recvbufferlen;
int sendbufferlen;
int sockcount;
int allevbufferlen;
int sendindex;
Stack<int> sockstack;
Object stackobj = new Object();
Socket acceptsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
SocketAsyncEventArgs acceptargs = new SocketAsyncEventArgs();
public event Action<int, int> RecvComplete;
public event Action<int> AcceptComplete;
public event Action<int> SendComplete;
public event Action<int> CloseComplete;
byte[] inValue = new byte[] { 1, 0, 0, 0, 0x88, 0x13, 0, 0, 0x88, 0x13, 0, 0 };
public Server(int skcount, int rvbufferlen, int sdbufferlen, int queuecount, string ipadr, int port)
{
buffers = new byte[skcount * rvbufferlen + sdbufferlen];
sockets = new Socket[skcount];
sendargs = new SocketAsyncEventArgs[skcount];
recvargs = new SocketAsyncEventArgs[skcount];
queues = new Queue<int>[skcount];
objs = new Object[skcount];
states = new int[skcount];
recvbufferlen = rvbufferlen;
sendbufferlen = sdbufferlen;
sockcount = skcount;
allevbufferlen = skcount * rvbufferlen;
sendindex = 0;
sockstack = new Stack<int>(skcount);
for (int i = 0; i < skcount; i++)
{
sockstack.Push(skcount - 1 - i);
sendargs[i] = new SocketAsyncEventArgs();
sendargs[i].UserToken = i;
recvargs[i] = new SocketAsyncEventArgs();
recvargs[i].UserToken = i;
queues[i] = new Queue<int>(queuecount);
objs[i] = new Object();
recvargs[i].SetBuffer(buffers, i * rvbufferlen, 2);
sendargs[i].SetBuffer(buffers, allevbufferlen + sendindex, rvbufferlen);
recvargs[i].Completed += new EventHandler<SocketAsyncEventArgs>(Receive_Completed);
sendargs[i].Completed +=new EventHandler<SocketAsyncEventArgs>(Send_Completed);
}
acceptargs.Completed +=new EventHandler<SocketAsyncEventArgs>(acceptargs_Completed);
acceptsock.Bind(new IPEndPoint(IPAddress.Parse(ipadr), port));
acceptsock.Listen(10);
acceptsock.AcceptAsync(acceptargs);
}
void acceptargs_Completed(object sender, SocketAsyncEventArgs e)
{
int m = -1;
if (e.SocketError == SocketError.Success && e.LastOperation == SocketAsyncOperation.Accept
&& e.AcceptSocket != null)
{
lock (stackobj)
m = sockstack.Pop();
sockets[m] = e.AcceptSocket;
}
e.AcceptSocket = null;
acceptsock.AcceptAsync(e);
if (m != -1)
{
Interlocked.CompareExchange(ref states[m], 1, 0);
AcceptComplete.Invoke(m);
sockets[m].IOControl(IOControlCode.KeepAliveValues, inValue, null);
sockets[m].ReceiveAsync(recvargs[m]);
}
}
void Receive_Completed(object sender, SocketAsyncEventArgs e)
{
bool yichang = false;
int sockindx = e.Offset / recvbufferlen;
if (e.SocketError == SocketError.Success)
{
if (e.LastOperation == SocketAsyncOperation.Receive)
{
if (e.BytesTransferred > 0)
{
if (e.BytesTransferred == e.Count)
{
int os = sockindx * recvbufferlen;
int len = BitConverter.ToInt16(buffers, os);
if (e.Offset % recvbufferlen < 2)
e.SetBuffer(os + 2, len - 2);
else
{
int indx = getsendindex(len);
Buffer.BlockCopy(e.Buffer, os, e.Buffer, indx, len);
e.SetBuffer(os, 2);
if (RecvComplete != null)
RecvComplete.BeginInvoke(sockindx, indx, null, null);
}
}
else
e.SetBuffer(e.Offset + e.BytesTransferred, e.Count - e.BytesTransferred);
}
else
yichang = true;
}
}
else
yichang = true;
if (yichang)
{
CloseSocket(sockindx);
}
else
sockets[sockindx].ReceiveAsync(e);
}
void Send_Completed(object sender, SocketAsyncEventArgs e)
{
bool busy = false;
int indx = (int)e.UserToken;
if (e.SocketError == SocketError.Success)
{
if (e.LastOperation == SocketAsyncOperation.Send)
{
lock (objs[indx])
{
queues[indx].Dequeue();
if (queues[indx].Count > 0)
busy = true;
}
if (busy)
{
int sdindx = queues[indx].Peek();
e.SetBuffer(sdindx, BitConverter.ToInt16(buffers, sdindx));
try { sockets[indx].SendAsync(e); }
catch { }
}
if (SendComplete != null)
SendComplete.Invoke(indx);
}
}
else
CloseSocket(indx);
}
public int getsendindex(int len)
{
int index = (int)(((uint)Interlocked.Add(ref sendindex, len)) % sendbufferlen);
if(index - len < 0)
index = (int)(((uint)Interlocked.Add(ref sendindex, len)) % sendbufferlen);
return index - len + allevbufferlen;
}
public void Send(int sockindx, int sendindx)
{
bool busy = false;
lock (objs[sockindx])
{
if (queues[sockindx].Count > 0)
busy = true;
queues[sockindx].Enqueue(sendindx);
}
if (!busy)
{
sendargs[sockindx].SetBuffer(sendindx, BitConverter.ToInt16(buffers, sendindx));
try { sockets[sockindx].SendAsync(sendargs[sockindx]); }
catch { }
}
}
public void CloseSocket(int sockindx)
{
if (Interlocked.CompareExchange(ref states[sockindx],0,1) == 1)
{
try
{
if (CloseComplete != null)
CloseComplete.Invoke(sockindx);
try { sockets[sockindx].Shutdown(SocketShutdown.Both); }
catch { }
finally { sockets[sockindx].Close(); }
}
catch { }
finally
{
lock (objs[sockindx])
{
sockets[sockindx] = null;
queues[sockindx].Clear();
}
lock (stackobj)
sockstack.Push(sockindx);
}
}
}
}
{
public byte[] buffers;
SocketAsyncEventArgs sendargs;
SocketAsyncEventArgs recvargs;
SocketAsyncEventArgs connargs;
Queue<int> queues;
Object objs;
int state;
int recvbufferlen;
int sendbufferlen;
int sendindex;
Socket acceptsock;
public event Action<int> RecvComplete;
public event Action ConnComplete;
public event Action SendComplete;
public event Action CloseComplete;
byte[] inValue = new byte[] { 1, 0, 0, 0, 0x88, 0x13, 0, 0, 0x88, 0x13, 0, 0 };
public Client(int rvbufferlen, int sdbufferlen, int queuecount, string ipadr, int port)
{
acceptsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
buffers = new byte[rvbufferlen + sdbufferlen];
sendargs = new SocketAsyncEventArgs();
recvargs = new SocketAsyncEventArgs();
connargs = new SocketAsyncEventArgs();
queues = new Queue<int>(queuecount);
objs = new Object();
recvbufferlen = rvbufferlen;
sendbufferlen = sdbufferlen;
sendindex = 0;
connargs.Completed += new EventHandler<SocketAsyncEventArgs>(acceptargs_Completed);
recvargs.Completed += new EventHandler<SocketAsyncEventArgs>(Receive_Completed);
recvargs.SetBuffer(buffers, 0, 2);
sendargs.Completed += new EventHandler<SocketAsyncEventArgs>(Send_Completed);
sendargs.SetBuffer(buffers, recvbufferlen + sendindex, recvbufferlen);
connargs.RemoteEndPoint = new IPEndPoint(IPAddress.Parse(ipadr), port);
acceptsock.ConnectAsync(connargs);
}
public void Connect()
{
acceptsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
acceptsock.ConnectAsync(connargs);
}
void acceptargs_Completed(object sender, SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success && e.LastOperation == SocketAsyncOperation.Connect
&& e.ConnectSocket != null)
{
if (ConnComplete != null)
ConnComplete.Invoke();
Interlocked.CompareExchange(ref state, 1, 0);
acceptsock.IOControl(IOControlCode.KeepAliveValues, inValue, null);
acceptsock.ReceiveAsync(recvargs);
}
else
acceptsock.ConnectAsync(connargs);
}
void Receive_Completed(object sender, SocketAsyncEventArgs e)
{
bool yichang = false;
if (e.SocketError == SocketError.Success)
{
if (e.LastOperation == SocketAsyncOperation.Receive)
{
if (e.BytesTransferred > 0)
{
if (e.BytesTransferred == e.Count)
{
int len = BitConverter.ToInt16(buffers, 0);
if (e.Offset < 2)
e.SetBuffer(2, len - 2);
else
{
int indx = getsendindex(len);
Buffer.BlockCopy(e.Buffer, 0, e.Buffer, indx, len);
e.SetBuffer(0, 2);
if (RecvComplete != null)
RecvComplete.Invoke(indx);
}
}
else
e.SetBuffer(e.Offset + e.BytesTransferred, e.Count - e.BytesTransferred);
}
else
yichang = true;
}
}
else
yichang = true;
if (yichang)
{
CloseSocket();
}
else
acceptsock.ReceiveAsync(e); }
void Send_Completed(object sender, SocketAsyncEventArgs e)
{
bool busy = false;
if (e.SocketError == SocketError.Success)
{
if (e.LastOperation == SocketAsyncOperation.Send)
{
lock (objs)
{
queues.Dequeue();
if (queues.Count > 0)
busy = true;
}
if (busy)
{
int sdindx = queues.Peek();
e.SetBuffer(sdindx, BitConverter.ToInt16(buffers, sdindx));
try { acceptsock.SendAsync(e); }
catch { }
}
if (SendComplete != null)
SendComplete.BeginInvoke(null, null);
}
}
else
CloseSocket();
}
public int getsendindex(int len)
{
int index = (int)(((uint)Interlocked.Add(ref sendindex, len)) % sendbufferlen);
if (index - len < 0)
index = (int)(((uint)Interlocked.Add(ref sendindex, len)) % sendbufferlen);
return index - len + recvbufferlen;
}
public void Send(int sendindx)
{
bool busy = false;
lock (objs)
{
if (queues.Count > 0)
busy = true;
queues.Enqueue(sendindx);
}
if (!busy)
{
sendargs.SetBuffer(sendindx, BitConverter.ToInt16(buffers, sendindx));
try { acceptsock.SendAsync(sendargs); }
catch { }
}
}
public void CloseSocket()
{
if (Interlocked.CompareExchange(ref state, 0, 1) == 1)
{
try
{
if (CloseComplete != null)
CloseComplete.Invoke();
try { acceptsock.Shutdown(SocketShutdown.Both); }
catch { }
finally { acceptsock.Close(); }
}
catch { }
finally
{
lock (objs)
{
acceptsock = null;
queues.Clear();
}
}
}
}
}
使用lock
lock需要指定一个私有的变量,保证类的外部是无法访问的.
1.读取i的值
2.i加1
3.把上一步计算得的值存入i变量两个线程就可能出现
线程一读I(假设为1)
线程二读I(还为1)
线程一把计算I+1(2)的值 并存入I
线程一把计算I+1(2)的值 并存入I结果就出现了竞态
干吗不lock(A)。