【问题标题】:Lock on dedicated lock-object causes deadlock锁定专用锁定对象会导致死锁
【发布时间】:2014-02-14 09:00:31
【问题描述】:

昨天我遇到了一个奇怪的问题,这让我很头疼。我有一个带有 Server 类的服务器应用程序,该类又派生自 Connection 类。 Connection 类提供有关连接状态和关闭连接可能性的信息

public bool Connected
{
    get
    {
        if (connection != null)
        {
            lock (lockObject)
            {
                bool blockingState = connection.Blocking;

                try
                {
                    connection.Blocking = false;
                    connection.Send(new byte[1], 1, 0);
                }
                catch (SocketException e)
                {
                    if (!e.NativeErrorCode.Equals(10035))
                    {
                        return false;
                    }
                     //is connected, but would block

                }
                finally
                {
                    connection.Blocking = blockingState;
                }

                return connection.Connected;

            }

        }

        return false;
   }
}

public virtual void CloseConnection()
{
    if (Connected)
    {
        lock (lockObject)
        {
            connection.Close();
        }
    }
}

Server 类负责实际发送数据

private void ConnectAndPollForData()
{
    try
    {
        TcpListener listener = new TcpListener(Port);

        listener.Start();
        while (true)
        {
            connection = listener.AcceptSocket();

            string currentBuffr = string.Empty;
            const int READ_BUFFER_SIZE = 1024;
            byte[] readBuffr = new byte[READ_BUFFER_SIZE];

            while (Connected)
            {
                int bytesReceived;

                lock (lockObject)
                {
                    bytesReceived = connection.Receive(readBuffr, READ_BUFFER_SIZE, SocketFlags.None);
                }
                currentBuffr += ASCIIEncoding.ASCII.GetString(readBuffr, 0, bytesReceived);

                //do stuff

        }
    }
    catch(ThreadAbortException)
    {
        Thread.ResetAbort();
    }
    finally
    {

    }
}

public void SendString(string stringToSend)
{
    stringToSend += "\r\n";


    if(Connected)
    {
        lock(lockObject)
        {
            connection.Send(ASCIIEncoding.UTF7.GetBytes(stringToSend));
        }
    }

}

没有其他对连接对象的显式访问。 ConnectAndPollForData 函数在单独的线程中执行。每当我在这个版本中运行主机时(我目前使用的是非线程安全版本,这会导致其他问题),它会在通过 TCP 接收到很多行后挂起。暂停调试器告诉我,一个线程尝试使用 Connected 锁执行代码,而另一个线程尝试在 ConnectAndPollForData 锁中接收数据。这种行为对我来说似乎很奇怪,因为我希望在第一个锁中执行代码,然后再执行第二个。在使用Deadlocking lock() method'Deadlock' with only one locked object? 中的回调时似乎确实存在类似的问题,但这里的情况有点不同,因为在我的情况下(我认为)锁中的代码不应该发出任何自己试图发出的事件获取对象上的锁。

【问题讨论】:

    标签: c# multithreading deadlock


    【解决方案1】:

    假设它首先在第二种方法中获得了锁。所以它持有锁,并等待数据。目前尚不清楚这是直接接收第一种方法发送的数据,还是正在寻找来自无关服务器的回复-对发送中的消息的回复第一种方法。但无论哪种方式,我都假设在发送出站消息之前不会有数据传入。

    现在考虑:出站消息无法发送,因为您持有排他锁。

    所以是的,你自己陷入了僵局。基本上,不要那样做。即使在同一个套接字上,也无需在入站和出站套接字操作之间进行同步。而且由于在同一个套接字上拥有并发读取器或并发写入器几乎没有意义,我猜你实际上根本不需要那些locks。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-18
      • 2013-07-24
      • 1970-01-01
      • 1970-01-01
      • 2012-02-21
      • 1970-01-01
      • 1970-01-01
      • 2020-07-31
      相关资源
      最近更新 更多