为什么 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->Release()
时,mtx->Acquire()
没有锁定互斥锁,在运行时没有任何变化,两个线程可以同时访问相同的共享资源,这不是我想要的。我在Linux环境中使用p_threads,当互斥体被锁定时,其他线程等待它变得可用。如何使用 C++ CodeGear 2009 获得相同的结果?
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. 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 ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
其他的东西可以解释你的问题,因为
TMutex::Acquire
确实获取了互斥体对象的锁。TMutex
的实现如下所示:WaitFor
调用WaitForMultipleObjectsEx
传递互斥体句柄。最有可能的是,您实际上以某种方式拥有多个互斥锁,但我无法确定,因为我看不到您的所有代码。
最后,对于进程内同步,您应该更喜欢 Windows 临界区,它的性能比 Windows 互斥对象更好。这就是 RTL 中的
TCriticalSection
。更新后,很容易看到发生了什么。所有锁的使用都发生在主线程中。您调用
Synchronize
会导致该方法在主线程上执行。如果您直接从Execute
方法调用CheckLock
,那么您将按预期死锁。您需要对所有 GUI 调用使用
Synchronize
。从广义上讲,它的工作原理是向主线程发出信号,告知同步队列中有某些内容,然后等待主线程完成工作。它是一种异步方法。Something else is the explanation to your problem because
TMutex::Acquire
does indeed acquire a lock on the mutex object. The implementation ofTMutex
looks like this:And
WaitFor
callsWaitForMultipleObjectsEx
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 callCheckLock
directly from yourExecute
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.