开发者

Why does TMutex method Acquire() not lock a mutex?

So far I have this code:

****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->Releas开发者_如何学编程e();
}

The problem is, mtx->Acquire() does not lock a mutex, when I comment the mtx->Release(), nothing changes during runtime, both threads can access the same shared resource at the same time, witch is not what I want. I was using p_threads in Linux environment, and when the mutex is locked, other threads waits for it to become available. How can I achieve the same result using C++ CodeGear 2009 ?


Something else is the explanation to your problem because TMutex::Acquire does indeed acquire a lock on the mutex object. The implementation of TMutex looks like this:

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

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

And WaitFor calls WaitForMultipleObjectsEx passing the mutex handle.

Most likely is that you actually have more than one mutex somehow but I can't tell for sure since I can't see all of your code.

Finally, for within process synchronisation you should prefer the Windows critical section which performs better than the Windows mutex object. That is TCriticalSection in the RTL.


Following your update it is easy to see what is happening. All use of the lock happens in the main thread. You call Synchronize which results in the method executing on the main thread. If you call CheckLock directly from your Execute method then you will deadlock as intended.

You need to use Synchronize for all GUI calls. It works, broadly, by signaling the main thread that there is something in the synchronize queue and then waiting until the main thread has completed the work. It is an asynchronous method.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜