21

スレッドをスポーンして、その中で安全にpthread_create使用できますか?std::mutex

std::mutexとして実装されていれば問題ないと思いますが、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);
}

ところで、私はDebianWheezyを実行しています。

4

4 に答える 4

7

あなたは私のマシンでできました(Debianも)。しかし、これを安全と呼ぶかどうかはわかりません。

関連するファイルを見ると/usr/include/c++/4.7/i486-linux-gnu/bits/gthr-default.h、私の場合、pthreads APIへの1:1マッピングがあることがわかります。に正確に定義されているロックに<mutex>使用します。またはあなたはそれが宣言するのを見るでしょう__gthread_mutex_lockpthread_mutex_lockstd::threadtypedef __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

どの仕様でも機能するという保証はありませんが、唯一の実際のスレッドライブラリとしてpthreadを使用するOS上のC ++実装は、C ++スレッドの下でpthreadを使用する可能性が高いため、機能する可能性があります。

そのプラットフォームがpthreadもサポートしている場合でも(たとえば、Windows)、後でpthread以外のものを使用する他のプラットフォームにコードを移植しようとすると、問題が発生する可能性があります。

問題は、なぜわざわざそれを危険にさらすのかということです。C ++ 11を使用している場合は、同様std::mutexに使用してみませんか?std::thread

于 2013-03-12T17:59:18.723 に答える
3

両方ともstd::thread、指定されたオブジェクトのプラットフォーム実装を掘り下げることができるメソッドがありますstd::mutexnative_handleこれは、標準のスレッドライブラリがプラットフォームの実装とうまく機能するように設計されていることを私に教えてくれます。

余談ですが、さまざまなことstd::threadstd::mutex行うさまざまなオブジェクトです。スレッドを管理し、クロススレッド同期を提供します。結局、カーネルは手間のかかる作業を行います。

ですから、移植性について心配していなければ、なぜこれが問題になるのかわかりません。

余談ですが、プラットフォームで可能なより豊富な機能セットを提供するために、ネイティブプラットフォームの実装が必要になる場合があります。たとえば、BSDスレッドではさまざまな種類のスレッドが許可され、一部のスレッドライブラリでは新しいスレッドのスタックサイズを設定できます。C ++スレッドAPIは、移植可能な最小公分母です。

于 2016-12-11T22:28:41.970 に答える
0

あなたの質問が次の場合:あるタイプのミューテックスと別のタイプのミューテックスをランダムに自由に切り替えることができますか?その場合、答えはノーです(すべての最下層がpthread_mutexなどの同じ実装を使用しない限り)。

ただし、保護するリソースのグループが異なる場合は、1つのリソースグループを1つの実装で保護できます。実際には、セマフォを使用する方がよい場合もあります(つまり、セマフォは、書き込み用に1つのロック、読み取り用に多数のロックを定義するのに役立ちます)。

したがって、管理しているリソースのグループが4つある場合は、次を使用できます。

  • std :: mutex、
  • pthread_mutex、
  • boost :: mutex、
  • セマフォ。

できないことは、boost :: mutexを使用してセマフォによって保護されているデータにアクセスすること、またはその逆、またはstd::mutexを使用してpthread_mutexによって保護されているものを使用することです。

簡単な例として、コードの観点から、これはゲッターとセッターが次のように行われることを意味します。

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

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

2つの関数は同じミューテックス(ここ)を使用し、ミューテックスには1つのタイプがある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;
}

この2番目の例では、2つの異なるミューテックスを使用しますが、ロックインによってロックインset()がブロックされないため、期待どおりに機能しませんget()。その逆も同様です。したがって、それについて安全なものは何もありません(たとえ警備員の1人がSafeGuardと呼ばれていても)。

したがって、ルールは、m_valueという名前のミューテックスで保護する場合my_mutex、アクセスするときはいつでもミューテックスm_valueをロックする必要があるということですmy_mytex。このように一貫している限り、どの実装を使用してもかまいません。

于 2016-05-06T05:39:29.123 に答える