5

私のシナリオは次のようなものです。ユーザーがGUI要素を操作し、オーディオコールバック関数がUIによって設定された変数を読み取り、サンプルを計算してサンプルをバッファー(または任意のデータ構造)に格納し、バッファーがUIによって読み取られ、波形を描画します。 (ドローループで1秒間に60回)。

今、私が読​​んだいくつかのもの(Linuxオーディオ開発リストのスレッド、これこれ)によると、ロックを必要とせずに同時に読み取りと書き込みができるある種のデータ構造が必要です、または、ある種のデータ構造が必要です変数を渡すためのクロススレッド通知システム。

ただし、私が見たいくつかの 例では、C ++ stdライブラリのバニラベクトルを使用しています。これらは一方のスレッドから読み取り、もう一方のスレッドから書き込みます。プログラムを実行すると、正常に実行されます。

  1. どのような場合、ロックフリーのデータ構造を使用する必要がありますか?この種のクロススレッド通信を行いますか?
  2. ネットワークIOを受信し、他の2つのスレッドにデータを渡す必要があるMIDIやOSCコールバック関数などの別のスレッドを追加する場合、ロックフリー構造について心配する必要がありますか?
  3. 2番目の答えが「はい」の場合、どちらを使用するのが適切な構造ですか?
4

1 に答える 1

8

同じメモリにアクセスしているスレッド(読み取りまたは書き込み)がある場合は、ロックを使用するか、ロックのないデータ構造を使用する必要があります。そうしないと、複数のスレッドが同時にアクセスしているときに、データ構造が破損する(または破損しているように見える)可能性があります。

あなたが指している例は、事前に割り当てられた固定サイズのベクトルを使用しているようです。オーディオスレッドはこのバッファーに書き込んでおり、UIスレッドはそれを読み取っていますが、2つは同期されていません。2つは完全に同時に実行される可能性があるため、UIスレッドには、実際に読み取られているデータについての保証はありません。アップデートNから一部のデータを読み取り、アップデートN+1から一部のデータを読み取る場合があります。一部のデータを見逃したり、一部のデータを2回(またはそれ以上)読み取ったりする可能性があります。これは、オーディオアプリケーションを構築するための堅牢な方法ではありません。視覚化の結果は完全である必要はないため、単純な視覚化アプリには十分に「機能」しますが、記録または再生アプリケーションにはまったく適していません。

オーディオ再生には「リアルタイム」要件があるため、オーディオアプリケーションは(ロックを使用する代わりに)ロックフリーのデータ構造を使用することがよくあります。オーディオバッファに100ミリ秒のサウンドが含まれている場合は、これらのバッファを1秒間に10回満たす必要があります。そうしないと、オーディオの再生が途切れます。別の言い方をすれば、毎回バッファを埋める 期限が100ミリ秒あるということです。

この100ミリ秒の期限を逃す原因となる可能性のあるものはさまざまです。システムがビジー状態である場合、プロセスがスケジュールされない可能性があります。または、ページフォールトにより、ディスク読み取りが原因でプロセスが長時間ブロックされる可能性があります。たとえば、いくつか例を挙げます。ロックを取得しようとしているが、別のスレッドが100ミリ秒を超えてロックを保持している場合、これにより期限を逃してしまいます。これが、ロックの使用がオーディオアプリケーションに悪影響を与える可能性がある理由です。ロックを長時間保持する別のスレッドを使用すると、期限を逃す可能性があります。

ロックフリーのデータ構造では、待機するロックがないため、他のスレッドが進行を停止することはできません。オーディオI/Oの期限を簡単に設定できます。

しかし、ロックフリーアルゴリズムに興奮しすぎる前に、それらがはるかに微妙であり、ロックよりも正しく使用するにははるかに多くの専門知識が必要であることを知っておく必要があります。基本的に、この分野の専門家でない場合は、ロックフリーアルゴリズムを自分で作成しようとしないでください。おそらく、いくつかのロックフリーアルゴリズムの実装を備えた優れたオープンソースライブラリがあります。私は最近見ていません。

ただし、他の考えられる遅延の原因を回避するためにオーディオスレッドにも細心の注意を払っていない限り、ロックフリーアルゴリズムを使用するために必要な余分な作業は多かれ少なかれ無駄になることに注意してください。具体的には:

  • オーディオスレッドはメモリを使用してはいけませんmalloc()free()ほとんどのmalloc / free実装は内部でグローバルロックを取得します)

  • オーディオスレッドによってアクセスされるメモリがページアウトされていないことを確認する必要があります(例mlock():)

  • I / O呼び出しがブロックされる可能性があるため、オーディオスレッドはサウンドカード以外のI/Oを実行してはなりません。

非常に勤勉でこれらすべての手順を実行しているのでない限り、他のスレッドと共有されるデータにロックを使用することもできますが、ロックが非常に短時間保持されるようにしてください。たとえば、ロックを保持したままUIスレッドでmalloc()/ free()を実行したり、システムコールをブロックしたりしないでください。

于 2012-02-13T06:37:21.227 に答える