2

複数のスレッドと 1 つの共有オブジェクトを持つシステムで作業しています。非常に頻繁に読み取り操作を行うスレッドがいくつかありますが、書き込み操作はまれで、1 日に 3 ~ 5 回程度です。

同期に rwlock を使用していますが、ロック取得操作は常に発生するため、十分に高速ではありません。だから、私はそれを行うためのより速い方法を探しています。

おそらく、書き込み関数をアトミックにするか、書き込み中にすべてのスレッドを調べる方法です。移植性は難しい要件ではありません。GCC 4.6 で Linux を使用しています。

4

3 に答える 3

5

Have you considered using read-copy-update with liburcu? This lets you avoid atomic operations and locking entirely on the read path, at the expense of making writes quite a bit slower. Note that some readers might see stale data for a short time, though; if you need the update to take effect immediately, it may not be the best option for you.

于 2012-04-28T21:12:04.220 に答える
4

単一のオブジェクトではなく、複数のオブジェクトを使用することをお勧めします。オブジェクトを実際に共有する代わりに、オブジェクトとアトミックカウントを保持するオブジェクトを作成してから、スレッド間でこの構造へのポインターを共有します。

[ライターが1つしかない場合]各リーダーはポインターを取得し、カウンターをアトミックにインクリメントし、オブジェクトを使用します。読み取り後、カウンターをアトミックにデクリメントします。ライターは、元のオブジェクトのコピーを保持する新しいオブジェクトを作成し、それを変更します。次に、2つのポインターのアトミックスワップを実行します。ここで問題は古いオブジェクトを解放することです。そのため、リーダーの数が必要になります。ライターは、すべてのリーダーが作業を完了するまで古いオブジェクトの数をチェックし続ける必要があります。その時点で、古いオブジェクトを削除できます。

複数のライターがある場合(つまり、変数を更新するスレッドが複数ある場合)、同じアプローチに従うことができますが、ライターを使用する場合は、ポインターのコンペアアンドスワップ交換を行う必要があります。更新されたコピーが変更されたポインターの場合、ライターはプロセスを再開します(新しいオブジェクトを削除し、ポインターから再度コピーしてCASを再試行します)。

于 2012-04-28T19:04:53.363 に答える
1

おそらく、スピンロックを使用できます。スレッドは、ロックが解除されるまでビジー状態になります。スレッドが長期間ロックされていない場合、ロックとロック解除がより少ない命令で完了するため、ミューテックスよりもはるかに効率的です。

spinlock はオプションですが POSIX pthread の一部であるため、システムに実装されているかどうかはわかりません。ubuntu の C プログラムでそれらを使用しましたが、c99 の代わりに -std=gnu99 でコンパイルする必要がありました。

于 2012-04-29T01:55:59.747 に答える