静态和动态pthread互斥初始化

static and dynamic pthread mutex initialization

本文关键字:初始化 pthread 动态 静态      更新时间:2023-10-16

我正在阅读《高级Linux编程》一书。

Mutex可以通过以下方式动态初始化使用init函数:

  pthread_mutex_t theMutex;
  pthread_mutex_init(&theMutex, NULL);

Mutex可以通过宏静态初始化

 pthread_mutex_t result = PTHREAD_MUTEX_INITIALIZER;

书中说,如果我们创建互斥锁是动态的,互斥锁将在堆区域创建,所以我们必须手动删除它。

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

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

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

尽管这个问题已经过时了,但只要它是自动处理的,并且我既没有发现现有的答案令人满意,也没有找到一个好的欺骗目标,我就会试一试。

Mutex可以通过宏静态使用init函数[…或…]来动态初始化

将初始化本身描述为静态或动态是一个糟糕的措辞,因为这些术语与存储分配和持续时间的关系更密切。这是一个不同的、尽管相关的考虑因素,这个问题似乎混淆了这里和以后的概念。此外,POSIX的一些版本将PTHREAD_MUTEX_INITIALIZER限定为专门适用于具有静态存储持续时间的互斥体,对它是否也可以用于具有自动存储持续期的互斥体保持沉默,而当前版本省略了这一限定。据我所知,没有一个pthreads实现提供了一个PTHREAD_MUTEX_INITIALIZER,它在初始化静态和自动分配的互斥对象时不能同样好地工作。

书中说,我们必须把";pthread_mutex_destroy(&mutex)";如果我们动态地创建互斥,互斥将在堆区域中创建,所以我们必须手动删除它。

如果我正确地理解了这本书,或者至少理解了它,那么这里就有点误解,导致了本末倒置的局面。互斥体本身的存储驻留在堆上将是该互斥体的存储动态分配的结果;动态初始化";经由CCD_ 3。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()的(重新)初始化都不会自动使互斥进程共享。一个人需要使用一个互斥属性对象来指定,如果这是他想要的。

我的理解正确吗?

没有。它似乎总体上相当混乱,在几个细节上完全错误。请参见上文。

我认为使用静态分配的互斥,同一程序的线程只能共享它,直到他们的作用域结束,

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

但是动态分配了互斥,不同程序的线程将能够与互斥体交互。

你所说的不同程序是什么意思?如果你指的是进程间通信,那么不是。

看看这个SO的答案,它看起来有点复杂。

如果可能的话,我建议你使用boost库,或者如果你的编译器支持它,std::thread C++11扩展(在编程C++时)。

对于静态互斥体来说,使用PTHREAD_MUTEX_INITIALIZER不是强制性的,但它是可用的。它为互斥对象设置了一组常见的默认属性——还有一些其他初始化程序用于递归和错误检查互斥对象,而不是普通的"快速互斥对象"。可以将其视为简单地将值分配给不透明pthread_mutex_t结构的成员。pthread_mutex_init对属性进行了一系列验证,但实际上并没有分配任何内容。

IIRC对互斥体调用destroy会将互斥体的"种类"设置为无效值,因此尝试再次使用它会失败。在此之前,它还试图查看互斥体当前是否在其他地方使用,如果是,它将返回EBUSY。我这里没有nptl源代码要验证,但我认为仅此而已。