2

同僚の Visual Studio 2008 C++03 アプリケーション アプリケーションをレビューしていて、スレッド同期プリミティブ (下記) の実装に出くわしました。

正しく実装されていると仮定するとSyncObject、以下のコードでブール値を使用して、リソースがロックされているかロック解除されているかを知ることはスレッドセーフですか? いいえの場合、「ThreadA」がこれを行い、「ThreadB」がその状況を行うので、あなたの論理を理解できますか?

class CMyLock
{
public:
    CMyLock(SyncObject* object) 
        : object_(object), acquired_(false) 
    { 
    };

    // return true if the resource is locked within the given timeout period
    bool Lock(DWORD dwTimeOut = INFINITE)
    {
        acquired_ = object_->Lock(dwTimeOut);
        return acquired_;
    };

    // return true if the resource is unlocked
    bool Unlock()
    {
        if (acquired_)
            acquired_ = !object_->Unlock();
        return !acquired_;
    };

    // return true if the resource is locked
    bool IsLocked() { return acquired_; };

private:
    bool acquired_;
    // some thread synchronization primitive
    SyncObject* object_;
};
4

4 に答える 4

2

スレッドセーフではありません。

戻りの直後m_pObject->Unlock()に、待機中の別のスレッドが戻り、 true にm_pObject->Lock(dwTimeOut)設定されると、ロック解除スレッドが false に設定され、ロックされた状態が誤って上書きされます (オブジェクトがロックされている間、IsLocked は false を返します)。m_bAcquiredm_bAcquired

于 2012-05-23T13:31:55.323 に答える
2

このコードには重大な問題がいくつか見られます。コードレビューでは、私はそれを拒否します。

  1. このクラスが何を意図しているのかは明確ではありません。プリミティブへの薄いプロキシである可能性があります。自動ロッカーかもしれません。どちらの場合も、設計が間違っており、ドキュメント (なし) には詳しく説明されていません。

  2. RAII は使用しません。これは、このオブジェクトが何を意図していても良い考えですが、自動ロッカーの場合は特に重要です。

  3. 独自の状態を保持しているため、同じスレッド内の他のインスタンスと同期していない可能性があります。たとえば、スレッド A でこのオブジェクトの 2 つのインスタンスを作成し、一方を に設定しlockedて他方の状態を確認すると、メッセージは表示されますlockedが、表示されません。

  4. おそらく最も重要なことは、せいぜい車輪を再発明することです。

于 2012-05-23T13:38:54.633 に答える
1

短い答え:いいえ

読み取りのためにもロックする必要があります。そうしないと、古い状態が表示されるリスクがあります。

于 2012-05-23T13:28:32.860 に答える
1

いいえ、そうではありません-少なくとも私が見ることができるものから。1 つのスレッドが lock を呼び出してロックを取得し、別のスレッドが m_bAcquired にアクセスしてから、ロックの原因となったスレッドによって更新されることがあります。

そのため、Matthieu M. が述べたように、読み取りにもロックが必要です。

A: m_pObject がロックされた後、m_bAcquired が設定される前のロック B: IsLocked --> false を返す A - まだロック中: m_pObject = true

したがって、B は誤った情報を持っています。

その他の問題: ロック解除は m_bAcquired に依存しています。

このオブジェクトは、1 つのスレッド内から使用するためのものだと思います。したがって、各スレッドには独自の CSingleLock インスタンスがありますが、それらはすべて同じ SyncObject を使用します。この場合、SyncObject のみがスレッド セーフである必要があり、動作します。

于 2012-05-23T13:30:49.887 に答える