为什么TMutex方法Acquire()没有锁定互斥锁?

时间:2011-10-13 11:30:26

标签: c++ multithreading mutex c++builder

到目前为止,我有这段代码:

****SimpleForm.h****
class TForm1 : public TForm
{
__published:    // IDE-managed Components
    TMemo *Memo1;
    TButton *Button1;
    void __fastcall Button1Click(TObject *Sender);
private:    // User declarations
    TMutex *mtx;
public:     // User declarations
    __fastcall TForm1(TComponent* Owner);
};

****SimpleForm.cpp****
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
    mtx = new TMutex(true);
    WorkerThread *wt = new WorkerThread(false, mtx);
}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    mtx->Acquire();
        Memo1->Lines->Add("Locked...");
    mtx->Release();
}

****WorkerThread.h****
class WorkerThread : public TThread
{
private:
    TMutex *mtx;
protected:
    void __fastcall Execute();
public:
    __fastcall WorkerThread(bool CreateSuspended, TMutex *mtx);
    void __fastcall CheckLock();
};
****WorkerThread.cpp****
__fastcall WorkerThread::WorkerThread(bool CreateSuspended, TMutex *mtx)
    : TThread(CreateSuspended)
{
    this->mtx = mtx;
}

void __fastcall WorkerThread::Execute()
{
    while(true){
        Sleep(1000);
        Synchronize(CheckLock);
    }

}

void __fastcall WorkerThread::CheckLock(){
    this->mtx->Acquire();
    Form1->Memo1->Lines->Add("Locked from thread");
    //this->mtx->Release();
}

问题是,mtx->Acquire()没有锁定互斥锁,当我评论mtx->Release()时,运行时没有任何变化,两个线程可以同时访问同一个共享资源,女巫不是什么我想要。我在Linux环境中使用p_threads,当互斥锁被锁定时,其他线程等待它变得可用。如何使用C ++ CodeGear 2009获得相同的结果?

1 个答案:

答案 0 :(得分:0)

其他问题是对您的问题的解释,因为TMutex::Acquire确实获得了对互斥锁对象的锁定。 TMutex的实现如下所示:

procedure TMutex.Acquire;
begin
  if WaitFor(INFINITE) = wrError then
    RaiseLastOSError;
end;

procedure TMutex.Release;
begin
  if not ReleaseMutex(FHandle) then
    RaiseLastOSError;
end;

WaitFor调用WaitForMultipleObjectsEx传递互斥锁句柄。

最有可能的是,你实际上有多个互斥锁,但我无法确定,因为我看不到你的所有代码。

最后,对于进程内同步,您应该更喜欢Windows关键部分,该部分的性能优于Windows互斥对象。这是RTL中的TCriticalSection


在您的更新后,很容易看到发生了什么。锁的所有使用都发生在主线程中。您调用Synchronize会导致该方法在主线程上执行。如果您直接从CheckLock方法拨打Execute,则会按预期死锁。

您需要对所有GUI调用使用Synchronize。它广泛地通过向主线程发信号通知同步队列中存在某些内容然后等待主线程完成工作。这是一种异步方法。