不要在消息处理中使用线程锁定,会死锁的

"如果线程A锁住了记录1并等待记录2,而线程B锁住了记录2并等待记录1,这样两个线程就发生了死锁现象。"

如果只有一个线程锁定那么只要安全解锁了是不会死锁的,但特殊的情况是在 线程中使用了 sendmessage 而某个消息处理中又使用了该线程锁定就会形成死锁了.

原因是线程锁定是一个等待,而 sendmessage 又是一个等待,在消息队列中使用线程锁定同时在线程中使用 sendmessage 那么毫无疑问会发生死锁.

对于我来说这主要发生在已经做了线程,但新接到一个任务后不想再开线程而偷懒去使用定时器,这时死锁不可避免的发生了.为了验证将定时器间隔缩小你就会体会到了.

--------------------------------------------------

所以实际上是说不要混用线程和定时器处理可能访问同一资源的东西. (delphi , C++ 通用)

--------------------------------------------------

var
  i:Integer;
  user:TUserInfo;
begin
  //不应当用定时器实现,会死锁,因为  threadLock.Lock; 的其他线程是有可能发送 SendMessage 的,这时 sendmessage 会等待消息队列完成,
  //也就有可能会在 sendmessage 的时候等待定时器消息
  try
    ADOConnectionUser.Connected := True;
    ADOQueryUser.Close;
    ADOQueryUser.SQL.Clear;
    ADOQueryUser.SQL.Add('select * from AllOperators');
    ADOQueryUser.Open;

    //--------------------------------------------------
    //还是要锁定
    threadLock.Lock;
    try
      //TUserInfo.DelAllUser;
      for i := 0 to ADOQueryUser.RecordCount-1 do
      begin
        user:=TUserInfo.Create;
        user.userName := ADOQueryUser.fieldbyname('OperName').AsString;
        user.userPass := ADOQueryUser.fieldbyname('OperPsw').AsString;

        TUserInfo.AddUser(user.userName, user);
      end;

    finally
      threadLock.UnLock;
    end;
    //--------------------------------------------------

    MemoLog.Lines.Add('连接数据库刷新用户列表成功!')
  except
    //showme
    MemoLog.Lines.Add('连接数据库失败!')
  end;

end;

原文链接: https://www.cnblogs.com/-clq/archive/2012/05/02/2478823.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    不要在消息处理中使用线程锁定,会死锁的

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/49216

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月9日 上午12:54
下一篇 2023年2月9日 上午12:54

相关推荐