简体   繁体   English

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

[英]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->Release();
}

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. 问题是, mtx->Acquire()不会锁定互斥锁,当我注释mtx->Release()时,运行时没有任何变化,两个线程可以同时访问相同的共享资源,这不是我想要的想。 I was using p_threads in Linux environment, and when the mutex is locked, other threads waits for it to become available. 我在Linux环境中使用p_threads,并且互斥锁被锁定时,其他线程正在等待它变为可用。 How can I achieve the same result using C++ CodeGear 2009 ? 如何使用C ++ CodeGear 2009达到相同的结果?

Something else is the explanation to your problem because TMutex::Acquire does indeed acquire a lock on the mutex object. 因为TMutex::Acquire确实确实获得了互斥对象的锁,所以可以用其他方式解释您的问题。 The implementation of TMutex looks like this: TMutex的实现如下所示:

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. 然后WaitFor调用WaitForMultipleObjectsEx传递互斥锁句柄。

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. 最后,在进程同步中,您应该首选Windows关键部分,该部分的性能优于Windows互斥对象。 That is TCriticalSection in the RTL. 这就是RTL中的TCriticalSection


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. 您调用Synchronize ,这将导致该方法在主线程上执行。 If you call CheckLock directly from your Execute method then you will deadlock as intended. 如果直接从Execute方法中调用CheckLock ,则将按预期方式死锁。

You need to use Synchronize for all GUI calls. 您需要对所有GUI调用使用“ Synchronize ”。 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. 它是一种异步方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM