静态和动态pthread互斥初始化

时间:2013-11-27 18:49:10

标签: c++ c linux pthreads mutex

我正在关注高级Linux编程书。

可以通过动态初始化互斥锁  使用init函数:

  pthread_mutex_t theMutex;
  pthread_mutex_init(&theMutex, NULL);

可以通过宏

静态初始化互斥锁
 pthread_mutex_t result = PTHREAD_MUTEX_INITIALIZER;

这本书说,如果我们创建,我们必须调用“pthread_mutex_destroy(& theMutex)” mutex是动态的,mutex将在堆区域中创建,因此我们必须手动删除它。

但是如果我们静态地创建互斥锁,那么效果应该等同于动态初始化,通过调用pthread_mutex_init()并将参数attr指定为NULL,除了不执行错误检查。

我认为使用静态分配的互斥锁,同一程序的线程只能共享它,直到它们的作用域结束,但是使用动态分配的互斥锁,不同程序的线程将能够与互斥锁进行交互。

我的理解是否正确?如果有任何其他差异,请提及。

3 个答案:

答案 0 :(得分:1)

尽管这个问题已经很老了,只要它是自动碰撞的,而且我既没有找到令人满意的现有答案,也没有找到一个好的欺骗目标,我会试一试。

<块引用>

Mutex 可以通过使用 init 函数 [... or ...] 通过宏静态初始化

将初始化本身表征为静态或动态是一个糟糕的词选择,因为这些词与存储分配和持续时间更密切相关。这是一个独特的,尽管相关的考虑,而且这个问题似乎混合了这里和后面的概念。此外,POSIX 的某些版本将 PTHREAD_MUTEX_INITIALIZER 限定为专门适用于具有静态存储持续时间的互斥锁,但对于它是否也可用于具有自动存储持续时间的互斥锁保持沉默,而 the current version 则省略了该限定。据我所知,没有任何 pthread 实现提供了 PTHREAD_MUTEX_INITIALIZER,它在初始化静态和自动分配的互斥锁方面效果不佳。

<块引用>

书上说,如果动态创建互斥锁,必须调用“pthread_mutex_destroy(&theMutex)”,互斥锁会在堆区创建,需要手动删除。

如果我对这本书的理解正确,或者至少是对这本书的理解,那么这里就存在一些误解,导致出现车先马的情况。互斥体本身的存储驻留在堆上将是该互斥体动态分配存储的结果,而不是通过 pthread_mutex_init() 进行“动态初始化”。 C 语言的结构和语义规定,动态分配的互斥锁只能通过该函数进行初始化,但动态分配互斥锁的并不是使用该函数。

如果互斥锁是动态分配的,那么它的存储确实需要在不再需要时手动释放。如果它也通过 pthread_mutex_init() 初始化(而不是根本没有初始化),那么首先通过 pthread_mutex_destroy() 销毁它至少是一种好的风格,但这是一个单独的考虑。但是,pthread_mutex_init() 可能会动态分配额外的内存并将指向它的指针存储在互斥对象中。在这种情况下,人们会期望 pthread_mutex_destroy() 释放该内存,因此未能调用该函数可能会造成内存泄漏。

<块引用>

但是如果我们静态地创建互斥锁,效果将等同于 通过调用 pthread_mutex_init() 进行动态初始化 参数 attr 指定为 NULL,除了没有错误检查 执行。

这是使用 PTHREAD_MUTEX_INITIALIZER 初始化的效果,与互斥锁的分配方式没有直接关系。静态或自动分配的互斥锁可以通过任何一种方式进行初始化,因此分配类型并不能决定初始化方式。

<块引用>

我认为对于静态分配的互斥锁,同一程序的线程只能在其作用域结束之前共享它,但是对于动态分配的互斥锁,不同程序的线程将能够与互斥锁进行交互。

这又是混合概念。当互斥锁具有有效值时(并且仅在那时),它可以在其生命周期的部分期间使用。它的生命周期与其分配类型密切相关,但与它的初始化方式无关。与任何其他类型的对象一样,自动分配的互斥锁的生命周期在其作用域绑定的块的执行终止时结束,但静态或动态分配的互斥锁的生命周期与作用域无关。

在其生命周期内,互斥锁在每次成功初始化和下一次对其使用 pthread_mutex_destroy() 之间有效。有权访问给定互斥锁的所有进程的所有线程都可以在它有效时使用它。这与分配状态无关。这与初始化风格有关,pthreads 互斥锁默认不在进程间共享,所以那些最近通过 PTHREAD_MUTEX_INITIALIZER 初始化的互斥锁实际上不会在进程间共享。

这并不意味着自动或静态分配的 互斥量不能在进程之间共享,因为它们可以通过 pthread_mutex_init() 以使其进程共享的方式(重新)初始化。另一方面,无论其分配的性质如何,通过 pthread_mutex_init() 的(重新)初始化不会自动使互斥进程共享。需要使用一个互斥锁属性对象,该对象指定是否需要这样做。

<块引用>

我的理解正确吗?

没有。总体上似乎比较混乱,而且在几个细节上是完全错误的。见上文。

答案 1 :(得分:0)

  

我认为使用静态分配的互斥锁,相同程序的线程   只能分享它,直到它们的范围结束,

静态分配是在程序启动时进行的分配,在程序关闭时释放,因此它不会以范围结束。

  

但动态   分配互斥锁,不同程序的线程就可以了   与互斥锁互动。

不同的节目是什么意思?如果您的意思是进程间通信,那么没有。

看看this SO answer,它看起来有点复杂。

如果可能的话,我建议您使用boost library,或者如果您的编译器支持std::thread C++11 extentension(编程c ++时)。

答案 2 :(得分:0)

使用PTHREAD_MUTEX_INITIALIZER对于静态互斥锁不是强制性的,但它是可用的。它为互斥锁设置了一组常见的默认属性 - 还有一些其他初始值设定项用于递归和错误检查互斥锁,而不是股票'正常快速互斥锁'。可以把它想象为简单地为不透明pthread_mutex_t结构的成员赋值。 pthread_mutex_init对属性进行了大量验证,但实际上并没有分配任何内容。

IIRC在互斥锁上调用destroy会将互斥锁的“种类”设置为无效值,以便再次尝试再次使用它。在此之前,它还会尝试查看互斥锁当前是否在其他地方使用,如果存在,则会返回EBUSY。我没有这里的nptl源代码来验证,但我认为这是关于它的。