8

TCriticalSection如果我正确理解如何和Synchronize操作,我想在这里确认。

据我所知,现在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 以及被调用函数可能修改的任何内容?

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

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

4

1 回答 1

14

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

不,这是不正确的。SendMessage不会暂停任何东西。SendMessage 只是同步发送消息。在消息传递之前,该函数不会返回。即目标窗口的window proc已经执行完毕。并且因为窗口进程总是在拥有窗口的线程上被调用,这意味着调用线程可能需要被阻塞以等待窗口拥有的线程准备好执行窗口进程。它绝对不会挂起进程中的所有线程。

临界区如何知道我正在保护MyVariable1

它没有。确保所有MyVariable1需要保护的用途都得到保护,这完全取决于您。临界区是互斥体的一种形式。互斥锁确保只有一个执行线程可以在任何时刻保持互斥锁。

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

这也不是真的。“在所有线程中”是一个错误的想法。您需要考虑“在所有使用该变量的代码部分”。

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

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

于 2012-12-03T13:27:29.950 回答