3

我们有一个静态(单例)类,它将在多线程环境中使用。我们在其构造函数和其他 mrmber 函数中使用互斥锁。但是,析构函数没有互斥锁。析构函数执行一些任务,例如清理其他一些成员对象等。我们是否还需要在析构函数中使用互斥锁?

4

4 回答 4

3

在访问析构函数正在破坏的对象方面,不,它不应该使用互斥锁。调用代码负责确保析构函数被调用一次,并且只调用一次;那不是析构函数的责任。

在访问任何其他数据或资源方面,从析构函数访问它们并没有什么特别之处。无论是从这个析构函数还是任何普通函数调用它们,它们都需要或不需要使用互斥锁进行保护。

于 2009-06-02T09:38:00.327 回答
2

Dave 为析构函数提供的相同原理也适用于构造函数。虽然对象仍在构建中,但不应被任何其他线程访问。构造函数保证只能由一个线程运行(您不能构造两次),但您必须保证在对象完全构造之前没有线程访问该对象。

内部锁不应该是构造函数或析构函数对数据访问的责任。它们可用于线程同步的析构函数:如果对象已经对象内部(线程正在运行您的对象方法之一),以保证您不会在操作中间删除该对象。

这是在语言意义上使用构造函数析构函数的所有类型的类的通用方法。现在,对于单例来说,场景更加具体。通常,当您谈论单例的构造函数时,您实际上是在谈论创建对象的静态方法,而不是真正的构造函数。该静态方法通常具有可以包含静态互斥锁的同步机制。

在深入讨论什么是单例的破坏之前,您应该说明您的预期用途。单例是否会在应用程序生命周期内多次销毁和重新创建?它会被创造一次并永远存在吗?你是如何实现单例的?这些问题是决定是否、何时以及何地需要同步原语的起点。

于 2009-06-02T10:00:26.957 回答
0

如果你有多个线程试图删除一个对象,那么你的设计是严重错误的。

您必须仅在为您提供唯一实例的成员函数中使用同步,因为让多个对象请求一个实例是有意义的,但应该只有一个点您决定删除该对象并且不再使用它.

于 2009-06-02T09:54:13.147 回答
0

如果析构函数修改了一些全局数据(比如全局计数器等),或者一些共享资源,那么你需要互斥锁。否则,像这样保护析构函数意味着它的设计问题。当对象被其他线程使用时,任何时候线程都不应尝试删除该对象。

于 2009-06-02T10:00:43.493 回答