2011-10-13 135 views
1

到目前为止,我有这样的代码:为什么TMutex方法Acquire()不锁定互斥锁?

****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实现相同的结果?

回答

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这会导致方法在主线程上执行。如果您直接从Execute方法中调用CheckLock,那么您将按预期发生死锁。

对于所有GUI调用,您需要使用Synchronize。广义上讲,它的工作原理是向主线程发送同步队列中有某些内容,然后等待主线程完成工作。这是一种异步方法。

+0

刚刚用TCriticalSection测试过,结果相同。我检查了两个线程中的TMutext/TCriticalSection对象是相同的,但不知何故我无法让它们锁定。 –

+0

他们确实锁定。我日复一日地使用这些物体。还有一些我看不到的东西。 –

+0

我编辑了我的初始代码片段。现在完整的代码在那里。注意注释的mtx-> Release();行,为什么主线程仍然可以成功锁定互斥锁? –