3

たとえば、コンテナ マップを操作する 2 つのスレッドの場合、(パフォーマンス上の理由から) イテレータがまだ有効かどうかをテストする正しい方法は何ですか?
または、これを行うことができる唯一の間接的な方法になります。このサンプルコード:

#define _SECURE_SCL 1
//http://msdn2.microsoft.com/en-us/library/aa985973.aspx
#define _SECURE_SCL_THROWS 1

#include "map"
#include "string"
#include "exception"
#include "iostream"

using namespace std;

void main(void)
{
    map<string, string> map_test;
    map<string, string>::iterator iter_map_test;

    map_test [ "AAAAA" ] = "11111";
    map_test [ "BBBBB" ] = "22222";
    map_test [ "CCCCC" ] = "33333";

    iter_map_test = map_test.find ("BBBBB");

    map_test.erase ("BBBBB");

    try
    {
        string value = (*iter_map_test).second;
    }
    catch ( exception & e )
    {
            cout << e.what() << endl;
    }
    catch ( ... )
    {
            cout << "generic exception." << endl;
    }
}
4

5 に答える 5

9

std::maps はまったくスレッドセーフではありません。一度に複数のスレッドで同じマップを変更すると、無効化された反復子よりもはるかに悪い問題が発生します。別のスレッドによって変更されている間にマップから何かを読み取ることができるという保証があるとは思いません。

STL とスレッドに関するいくつかのページ:

于 2009-01-12T16:39:36.370 に答える
3

STLがスレッドセーフを提供していない場合std::mapIntelのTBBはスレッドセーフを提供しますconcurrent_hash_map(60ページと68ページ)。

スレッドセーフの問題はさておき、削除によって、削除されるイテレータ以外のイテレータが無効にならないことが保証されますstd::map 残念ながら、is_iterator_valid()保持しているイテレータを検証する方法はありません。

ハザードポインタのようなものを実装することは可能かもしれません、そしてTBBは同様に問題へのいくつかの回避策を持っています。

于 2009-01-12T18:53:35.447 に答える
2

スレッドの 1 つがマップを読み取るだけで、もう 1 つのスレッドがマップを操作している可能性があることがわかっている場合、最も簡単な解決策は、読み取り専用スレッドにマップのクローンを作成させ、クローンを反復処理させることです。

(注意: 私は STL よりも Java のコレクション クラスの方がはるかによく知っていますが、これは Java で行う方法です。)

于 2009-01-12T16:39:57.743 に答える
2

リーダー/ライター ソリューションを実装する場合、リーダーのすべての反復子を無効にするフラグをライターに設定させることができます。

http://en.wikipedia.org/wiki/Readers-writer_lock

Josh と Paul Tomblin が述べたように、同期せずにマップに書き込もうとはしません。

于 2009-01-12T16:46:19.120 に答える
1

ポインターが有効かどうかを判断できたとしても、問題は解決しません。排他的保証なしで単一のリソースを共有しています。これが失敗する理由です。

このスレッド シーケンスでは失敗します。

スレッド 0.................................スレッド 1

イテレータを取得 -> it0

it0が有効であることを確認してください

................................................イテレータを取得 -> it1

.........................................it1 が有効であることを確認します.

消去 (it0)

...................................................消去 (it1)

共有リソースにアクセスするためのセマフォを追加できます。

于 2009-04-17T15:17:40.550 に答える