2

MS Visual C++2012 の使用

クラスには型のメンバーがありますstd::atomic_flag

class A {
    public:
    ...
    std::atomic_flag lockFlag;
    A () { std::atomic_flag_clear (&lockFlag); } 
};

タイプAのオブジェクトがあります

A object;

2 つの (Boost) スレッドからアクセスできるユーザー

void thr1(A* objPtr) { ... }
void thr2(A* objPtr) { ... }

アイデアは、オブジェクトが他のスレッドによってアクセスされている場合、スレッドを待機することです。

問題は、そのようなメカニズムをatomic_flagオブジェクトで構築できるかどうかです。現時点では言うまでもありませんが、boost::mutex のような軽量化が必要です。

ちなみに、スレッドの1つに関連するプロセスは、多くの行を取得するdBaseへの非常に長いクエリであり、(各行を処理するときに)衝突が発生するコードの特定のゾーンでのみ中断する必要があり、できませんスレッド全体が終了するのを待ちますjoin()

各スレッドで次のように試しました:

thr1 (A* objPtr) {
    ...
    while (std::atomic_flag_test_and_set_explicit (&objPtr->lockFlag, std::memory_order_acquire)) {
        boost::this_thread::sleep(boost::posix_time::millisec(100));
    }
    ...  /* Zone to portect */

    std::atomic_flag_clear_explicit (&objPtr->lockFlag, std::memory_order_release);
    ...  /* the process continues  */
}

しかし、2 番目のスレッドがハングするため、成功しません。実は、そのatomic_flag_test_and_set_explicit機能に関わるメカニズムを完全には理解していません。そのような関数がすぐに戻るか、フラグがロックされるまで遅らせることができるかどうか。

また、常に値を設定し、前の値を返すような関数でロック機構を取得する方法も謎です。実際の設定のみを読み取るオプションはありません。

どんな提案でも大歓迎です。

4

3 に答える 3

8

ちなみに、スレッドの1つに関連するプロセスは、多くの行を取得するdBaseへの非常に長いクエリであり、(各行を処理するときに)衝突が発生するコードの特定のゾーンでのみ中断する必要があり、できませんスレッド全体が join() を完了するのを待ちます。

このようなゾーンは、クリティカル セクションと呼ばれます。クリティカル セクションを操作する最も簡単な方法は、相互排除によるロックです。

これがホットスポットであり、ロックの競合がパフォーマンスの問題であることを証明できない限り、提案されたミューテックスの解決策は実際に進むべき道です。アトミックおよび組み込み関数のみを使用したロックフリー プログラミングは非常に複雑であり、このレベルでは推奨できません。

これを行う方法を示す簡単な例を次に示します ( http://liveworkspace.org/code/6af945eda5132a5221db823fa6bde49aでライブ):

#include <iostream>
#include <thread>
#include <mutex>

struct A
{
    std::mutex mux;
    int x;

    A() : x(0) {}
};

void threadf(A* data)
{
    for(int i=0; i<10; ++i)
    {
        std::lock_guard<std::mutex> lock(data->mux);
        data->x++;
    }
}

int main(int argc, const char *argv[])
{
    A instance;
    auto t1 = std::thread(threadf, &instance);
    auto t2 = std::thread(threadf, &instance);

    t1.join();
    t2.join();

    std::cout << instance.x << std::endl;

    return 0;
}
于 2012-10-10T22:47:21.237 に答える
2

スピンロックを書き込もうとしているようです。はい、 でそれを行うことができますがstd::atomic_flag、代わりに を使用することをお勧めしますstd::mutex。自分が何をしているのか本当にわからない限り、アトミックを使用しないでください。

于 2012-10-11T08:03:32.160 に答える
1

尋ねられた質問に実際に答えるには: はい、std::atomic_flag を使用して、スピンロックと呼ばれるスレッド ロック オブジェクトを作成できます。

#include <atomic>

class atomic_lock
{
    public:
        atomic_lock()
            : lock_( ATOMIC_FLAG_INIT )
        {}

        void lock()
        {
            while ( lock_.test_and_set() ) { } // Spin until the lock is acquired.
        }

        void unlock()
        {
            lock_.clear();
        }

    private:
        std::atomic_flag lock_;
};
于 2012-10-26T05:16:52.820 に答える