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.
精彩评论