2012-03-14 27 views
11

如果我在主线程中创建了一个C++对象,然后启动另一个线程,并从该线程调用我创建的对象的公共成员函数,会发生什么情况?如果我从另一个线程调用一个对象成员函数会发生什么?

它是不同的,如果公共函数的参数,或者如果它操纵私有对象成员?

是否行为不同在Windows,Linux或Mac OS?

如果在栈上创建对象,会发生什么?

回答

9

有两点重要:

  • 第一,像往常一样,你需要esnure该实例的生命周期超过其使用期限。其次,跨多个线程访问变量需要同步以防止竞争条件。

这就是所有人。

+0

如果我在堆上创建了对象,当最后一个线程退出时,是否有任何简单的方法来删除对象? – neckTwi 2013-10-30 15:57:57

3

如果我在主线程中创建了一个C++对象,然后启动另一个线程,并从该线程我把我创建的对象的公共成员函数,会发生什么?

它取决于对象的生命周期。

如果在堆上创建对象(动态内存使用new),则另一个线程将正确访问对象的成员(假设没有竞争条件),除非通过在第一个线程中调用delete来终止对象的生命周期。

如果堆栈(本地)在第一个线程创建的对象,那么你将有一个* 未定义行为 *如果创建的对象的生命周期中的第二个线程被访问之前结束。

为什么你可以在第二个线程访问堆栈上的对象?

每个线程都有自己的堆栈,除非在线程的堆栈中创建的对象是有效的和活着你会试图访问不指向第二个线程任何有效的对象的地址位置。
注意,每个过程有一个地址空间,并在同一进程共享所有线程相同的地址空间,因此该变量的地址可以在所述第二线程访问。但是,您需要确保该地址包含有效的对象。

如果公共函数有参数或者它操作私有对象成员,它有什么不同?

访问说明和多线程都没有关系。
相同的访问说明符规则适用于所有线程。

是否行为不同在Windows,Linux或Mac OS?

对所有操作系统都保证了#1的答案。

+5

对不起,这是不正确的。如果物体的寿命大于线程的寿命,那么就可以。但要小心比赛条件。 – knivil 2012-03-14 08:03:47

+0

@knivil:对。我意识到我错过了这个说法。编辑。 – 2012-03-14 08:10:39

4
  1. 每个线程都有自己的堆栈,因此您可以有并发的执行流。让对象线程安全是你自己的责任。

  2. 没关系。但是,私人成员是竞争条件的候选人。

  3. 如果您在堆栈上创建对象,将无法从其他线程访问该对象。

+8

“如果您在堆栈上创建一个对象,将无法从其他线程访问该对象。”除非您将该对象的引用传递给另一个线程。 – 2012-03-14 08:04:04

+0

@NicolBolas:是的,你说得对,当然。我应该更好地说“可见”。 – Matthias 2012-03-14 08:51:13

2

与原始行为相比,如果在堆上创建,应该没有区别。但是,当然有一些罪魁祸首,通常在“线程安全”这个术语下是已知的。如果你从不同的线程访问同一个成员,你必须保证访问相同的资源不会导致“竞争条件”。

为避免竞争条件,您可以使用不同类型的“锁”,例如互斥锁等。使用锁对象时,还有另一个元凶:如果两个访问器互相等待,锁永远不会被释放。

2

它会工作得很好。对象不属于任何特定的线程,同样可以从任何地方调用。

但是,这很重要,同时在两个线程上调用成员函数会导致您在一个线程中更新某些数据的同时在另一个线程中读取数据时出现问题。您需要安排代码以确保不会发生这种情况,或确保您的线程协调访问(最有可能使用互斥锁)

2

如果您从同一个 线程调用它,会发生什么情况。相同的机器码被执行。唯一潜在的 不同之处在于,您可以有多个线程同时访问 处的对象;这是由你来防范(至少如果任何 的线程修改对象—否则,没有保护是 需要)。

对于堆栈中的对象,您必须考虑生命期问题 ,但无论如何都是如此;在全局变量中保存一个指向 堆栈上的对象的指针,然后保留定义对象为 的范围,并且全局变量变为悬挂指针;试图通过它访问对象 是未定义的行为(并且调用一个非静态成员函数 它被认为使用它)。无论是 的访问是来自同一个线程还是不同的线程都不会改变 的任何内容。

相关问题