2016-12-26 27 views
0

私はいくつかのスレッドが同時に呼び出すことができる関数を持っています。この関数には入力引数があります。たとえば、次の関数を考慮してください。マルチスレッドで入力引数を持つ関数を呼び出す

bool MyClass::run(QString moduleName) 
{ 
    qDebug() << QThread::currentThreadId(); 
    ... 
} 

この関数を使用するには2つのオプションがあります。まず、私は以下のようにrun関数の内部でミューテックスを使用することができます。以下のようにこの関数を呼び出すときに

... 
run("Reza"); // can be different for different threads 
... 
bool MyClass::run(QString moduleName) 
{ 
    qDebug() << QThread::currentThreadId(); 
    QMutexLocker locker(&runMutex); 
    ... 
} 

第二は、ミューテックスを使用している:

... 
runMutex.lock(); 
run("Reza"); // can be different for different threads 
runMutex.unlock(); 
... 
bool MyClass::run(QString moduleName) 
{ 
    qDebug() << QThread::currentThreadId(); 
    ... 
} 

正しいと優れている1?入力引数(moduleName)は最初のオプションで変更されますか? (私はこの関数に別の引数を渡すスレッドを呼び出すとき)を意味する

おかげさまであなたの助けをありがとう。 Reza

+1

どのリソースをミューテックスで保護しますか? (そして 'qDebug()'はあなたの最初のスニペットでは保護されていません)。 – Jarod42

+0

"better"を定義する... –

+0

@ Jarod42私はmutexで保護したい私の "run"関数にいくつかの共通リソースを持っています。私はqDebug()が保護されていないことを知っています。 – Reza

答えて

1

多くの場合、の両方がです。 mutexを内部的に取得する関数は、この関数を内部的に使用することで、より簡単で一般的に安全に使用できます。しかし、mutexを明示的に使用する場合は、ロックを保持している間に、run()メソッドで実行される操作に加えて、追加の操作を行う必要があることはよくあります。その場合、ロックを取得し、内部ロック関数を呼び出せない別の関数を持つことになります(mutexが再帰的なmutexでない限り、私は本当に良い考えではないと思います)。脱出の方法は、機能のバージョン(例えば、run_locked())またはロックが獲得されたと仮定する異なるパラメータを有するバージョンを有することである。

明示的なロックを使用しているとき(私は一般的に、ロックを使用してコードを考えることができないため、これを避けようとしています)、このような機能の対応するペアを持っていると便利です(私は通常stdファシリティを使用します)。ロックガードオブジェクトを渡す

bool MyClass::run(QString moduleName) { 
    QMutexLocker kerberos(&runMutex); 
    return this->run(kerberos, moduleName); 
} 
bool MyClass::run(QMutexLocker& kerberos, QString moduleName) { 
    // do whatever work is needed here 
} 

が周りの取得のガードがあることを確認します、つまり、ユーザーはただの取得ロックガードなしで取得するロックを期待して関数を呼び出すことはできません。間違ったロックのためにロックガードを取得することによって潜在的な誤用があります。

+0

@Kuhl迅速で包括的な回答をいただき、ありがとうございます。関数呼び出しの入力引数はどうですか?どのスレッドもそれ自身のスタックにそのコピーを持っているのですか、それともすべてのスレッドに共通していますか? – Reza

+1

@Reza:あなたは 'moduleName'を意味しますか?それが渡される方法は価値があり、すなわち、各スレッドはそれ自身の値を有する。私は 'QString'について何も知らない:共有表現(例えば、書き込み文字列上のコピー)を使用する場合、まだいくつかの問題があるかもしれない。 'std :: string'(少なくともC++ 11以降のC++実装)を使用する場合、文字列表現は共有されないことが保証され、値渡しの引数にアクセスする際にはロックは必要ありません。 –

+0

この答えは、ミューテックスの目的と、それによっておそらく保護されているリソースを明確に定義することを言及することなく、ほとんど意味をなさない。おそらくそれは質問がひどく不透明であるためです。 –

1

どちらの方法も正しいですが、最初の方が良い方法です。また、コードの可読性も提供します。

最初のオプションでは、入力引数(ローカル変数)の引数は常に安全です。各スレッドはそれ自身のスタックを持っているためです。

1

DietmarKühlは、言及されたアプローチの中から選択するための素敵な答えを提供しました。しかし、私は、クリティカルセクションを最小限に抑えることは、常に良い方法であると付け加えたい。したがって、 "run()"関数全体をロックする必要がない場合は、上記のどちらの方法も使用しないでください。ただし、 "run()"内の最小のクリティカルセクションを保護してください。

関連する問題