了解TCriticalSection和Synchronize

时间:2012-12-03 13:22:14

标签: multithreading delphi c++builder critical-section synchronize

如果我正确理解TCriticalSectionSynchronize的运作方式,我想在此确认。

据我所知Synchronize使用SendMessage(更新:或者至少在下面几条评论中提到的旧VCL版本中使用它)暂停当前正在执行的线程(以及任何其他线程)与PostMessage不同,它不会执行所需的功能(来自主线程)。在某种程度上SendMessage“在执行时停止”多线程。

但我不确定TCriticalSection。比方说我创建了这样的东西:

// Global variables somewhere in my code any thread can access
boost::scoped_ptr<TCriticalSection> ProtectMyVarAndCallFnction(new TCriticalSection);
int MyVariable1;
void CallMyFunctionThatAlsoModifiesMoreStuff() { /* do even more here */ };


// Thread code within one of the threads
try {
    ProtectMyVarAndCallFnction->Acquire();
    MyVariable1++;
    CallMyFunctionThatAlsoModifiesMoreStuff();
    }
__finally {
    ProtectMyVarAndCallFnction->Release();
    }

现在,我的问题是 - 关键部分如何“知道”我在这种情况下保护MyVariable1以及被调用的函数可以修改什么?

如果我理解正确 - 它没有 - 并且我有责任在任何线程中正确调用Acquire()想要更改MyVariable1或调用此函数(或执行任何两个)。换句话说,我认为TCriticalSection是用户定义的块,它定义了我分配给它的逻辑。它可以是一组变量或任何特定函数,只要我在可能写入此块的线程的所有内调用Acquire()或使用此函数。例如,“DiskOp”可能是我在磁盘上写入的TCriticalSection的名称,“Internet”可能是TCriticalSection的名称,它调用从Internet检索某些数据的函数。我弄错了吗?

另外,在这种情况下,TCriticalSection是否总是需要成为一种全局变量?

1 个答案:

答案 0 :(得分:14)

  

SendMessage暂停当前正在执行的线程(以及任何其他线程)。

不,那是不正确的。 SendMessage不会暂停任何内容。 SendMessage只是同步传递消息。在传递消息之前,该函数不会返回。也就是说,已经执行了目标窗口的窗口过程。并且因为窗口proc总是在拥有窗口的线程上调用,这意味着可能需要阻塞调用线程以等待窗口的拥有线程准备好执行窗口proc。它绝对不会暂停进程中的所有线程。

  

关键部分如何知道我正在保护MyVariable1

没有。完全取决于您确保所有需要保护的MyVariable1用途都得到保护。关键部分是互斥体的一种形式。互斥锁确保只有一个执行线程可以在任何时刻保存互斥锁。

  

当我在可能写入此块的所有线程中调用Acquire()或使用此函数时。

那也不是真的。 “在所有线程中”是一种误解。您需要考虑“使用变量的代码的所有部分”。

  

因此,关键部分是否总是需要成为一种全局变量?

不,关键部分可以是全局变量。但它不一定是。