21

我可以在其中安全地生成线程pthread_create并在其中使用吗?std::mutex

我认为如果std::mutex作为 a 实现pthread_mutex_t那么它会很好,但我没有在任何地方看到这个记录

例如:

#include <pthread.h>
#include <mutex>

namespace {
std::mutex global_lock;
}

void* thread_func(void* vp) {
    // std::mutex used in thread spawned with pthread_create
    std::lock_guard<std::mutex> guard(global_lock);
    // critical section
    return nullptr;
}

int main() {
    pthread_t tid;
    pthread_create(&tid, nullptr, thread_func, nullptr);
    pthread_join(tid, NULL);
}

顺便说一句,我正在运行 Debian Wheezy。

4

4 回答 4

7

你可以在我的机器上(Debian 也是)。但我不确定我是否会称之为保险箱。

如果你查看相关文件,/usr/include/c++/4.7/i486-linux-gnu/bits/gthr-default.h在我的例子中,你会看到将有一个 1:1 映射到 pthreads api。<mutex>用于__gthread_mutex_lock锁定,它在那里被精确定义pthread_mutex_lock。或者你会看到std::thread声明typedef __gthread_t native_handle_type;

我不知道是否有记录的方法来检查是否使用了 pthread。但是gthr-default.h定义_GLIBCXX_GCC_GTHR_POSIX_H为包含守卫,我认为只要定义了这个宏,您就可以假设您可以将它们混合使用。

编辑:鉴于@Wakely 的提示,我会写:

template <typename T>
using strip = typename std::remove_pointer<typename std::decay<T>::type>::type;

static_assert(std::is_same<strip<std::thread::native_handle_type>, pthread_t>::value,
              "libstdc++ doesn't use pthread_t");
于 2013-03-12T17:52:37.867 回答
7

在任何规范中都没有保证它会起作用,但很可能在使用 pthreads 作为其唯一真正的线程库的操作系统上的任何 C++ 实现都将在 C++ 线程下使用 pthreads,因此它可能会起作用。

如果您稍后尝试将代码移植到使用 pthread 以外的其他平台,即使该平台也支持 pthread(例如,windows),您可能会遇到问题。

问题是,为什么要麻烦和冒险呢?如果您使用的是 C++11 std::mutex,为什么不使用std::thread呢?

于 2013-03-12T17:59:18.723 回答
3

Both std::thread and std::mutex have a native_handle method which allows you to dig down to the platform implementation of the given object. This says to me that the standard threading library is designed to play nice with the platform implementation.

As an aside std::thread and std::mutex are different objects that do different things viz. manage threads and provide cross thread synchronization. In the end the kernel does the heavy lifting.

So if you are not worried about portability, I cannot see why this should be an issue.

As an aside, sometimes you may need the native platform implementation so as to provide you with the richer feature-set that the platform allows. For example BSD threading allows different types of threads and some threading libraries allow you to set the stack size of your new thread. The C++ threading APIs are a portable lowest common denominator.

于 2016-12-11T22:28:41.970 回答
0

如果您的问题是:我可以在一种互斥锁和另一种互斥锁之间随意切换吗?那么答案是否定的(除非所有底层都使用相同的实现,例如 pthread_mutex。)

但是,如果您想要保护不同的资源组,则可以使用任何一种实现来保护任何一组资源。实际上,有时使用信号量会更好(即信号量对于定义一个写锁,多个读锁很有用)。

因此,如果您要管理 4 组资源,则可以使用:

  • 标准::互斥体,
  • pthread_mutex,
  • 提升::互斥量,
  • 信号量。

你不能做的是使用 boost::mutex 来访问受信号量保护的数据,反之亦然,或者使用 std::mutex 来使用受 pthread_mutex 保护的东西。

举个简单的例子,就代码而言,这意味着 getter 和 setter 将以这种方式完成:

void set(int new_value)
{
    guard lock(my_mutex);
    m_value = new_value;
}

int get() const
{
    guard lock(my_mutex);
    return m_value;
}

这两个函数使用相同的互斥锁(此处my_mutex),显然互斥锁只有一种类型。

与此相反,您不能这样做:

void set(int new_value)
{
    guard lock(this_mutex_here);
    m_value = new_value;
}

int get() const
{
    SafeGuard lock(that_mutex_there);
    return m_value;
}

在第二个示例中,您使用了两个不同的互斥体,这不会按预期工作,因为锁定set()不会阻塞锁定,get()反之亦然。所以它没有什么安全的(即使其中一名警卫被称为 SafeGuard。)

所以规则是,如果您m_value使用名为 的互斥锁进行保护my_mutex,则任何时候访问m_value都必须锁定my_mytex互斥锁。您使用哪种实现并不重要,只要您以这种方式保持一致即可。

于 2016-05-06T05:39:29.123 回答