0

免責事項:BoostもC++11も許可されていません。

私はのインスタンスを作成し、Fooそれをいくつかのスレッドで操作するプログラムを持っています。次に、それらのスレッドがセグメンテーション違反に陥らないように、安全に削除したいと思います。

Fooスレッド関数が実行されるたびにミューテックスメンバーを追加してロックしました。異なるスレッドが互いに競合しないようにするため。

class Foo
{
    public:
        pthread_mutex_t mutex;
};

void* thread ( void* fooPtr )
{
    Foo* fooPointer = (Foo*) fooPtr;

    while ( 1 )
    {
        if ( fooPointer )
        {
            pthread_mutex_lock ( &fooPointer->mutex );
            /* some code, involving fooPointer */
            pthread_mutex_unlock ( &fooPointer->mutex );
        }
        else
        {
            pthread_exit ( NULL );
        }
    }
}

fooスレッドでエラーが発生しないように、安全に削除したいと思います。デストラクタを追加しましたFoo

Foo::~Foo()
{
    pthread_mutex_lock ( &mutex );
}

これで、すべてのスレッドが現在のループを終了するまで、オブジェクトは削除されません。

問題は、インスタンスが削除された後、ミューテックスのロックが解除されるかどうかです。インスタンスが削除された後、すべてのスレッドが終了しますか?答えはきっとno。だから私はデストラクタを変更しますが、今ではスレッドセーフではないようです:

Foo::~Foo()
{
    pthread_mutex_lock ( &mutex );
    pthread_mutex_unlock ( &mutex );
}

スレッドファンクションpthread_mutex_unlock ( &mutex );は、オブジェクトが削除された後および削除される前に、ミューテックスをロックしてインスタンスの操作を開始できますか?

4

3 に答える 3

11

あなたの質問の始まりから始めましょう:

私はFooのインスタンスを作成し、それをいくつかのスレッドで操作するプログラムを持っています。次に、それらのスレッドがセグメンテーション違反に陥らないように、安全に削除したいと思います。

使用中のオブジェクトは削除できません。ミューテックスの量はそれを修正しません。

Fooにデストラクタを追加しました

これは、が削除されている場合にのみ実行Fooされます。ただし、その内容はそれほど重要ではありません。他のスレッドがまだFooを使用しているときにdtorを呼び出すのは誤りです。

インスタンスが削除されたときにスレッドを安全に終了させたい。どうしてそれは可能ですか?

まあ、それは正しい質問です。私はあなたが使用するためにたくさんのコードを書くことができましたが、そのコードはただのコピーになりboost::weak_ptrます。だから、私は気にしません。ブーストコードを自分で取得するだけです。

ブーストは許可されていません。

では、なぜStackOverflowで質問しているのですか?これは基本的に同じライセンスです。

于 2012-09-17T08:52:14.140 に答える
1

ここで欠落しているのは、スレッド処理がいつ完了するかを決定する条件です。特定のオブジェクトインスタンスの削除は、良好な状態ではありません。オブジェクトが削除された場所を表示していません。これをコードで確認できれば、追加のコンテキストが役立ちます。

私が提案するのは、オブジェクトを削除する代わりに、オブジェクトにフラグを設定することです(たとえば、bool active())。このフラグはすべてのスレッドによってチェックされ、処理の停止を示すと、スレッドは停止します。現在Fooオブジェクトを削除している場所にこのフラグを設定します。次に、すべてのスレッドが停止したら、Fooオブジェクトを削除します。

オブジェクトを削除してミューテックスロックを取得できると期待すると、ミューテックスはFooのメンバーであるため、クラッシュするか、少なくとも不安定な動作が発生する可能性があり、オブジェクトとともに破棄されます。

これが私が意味することの例です:

class Foo
{
    public:
        void lockMutex();
        void unlockMutex();
        // Active should be mutex protected as well
        // Or you could consider using a pthread_rwlock
        bool active() {return active_;}
        void setActive(bool a) {active_ = a;}
    private:
        pthread_mutex_t mutex;
        bool active_;
};

void* thread ( void* fooPtr )
{
    Foo* fooPointer = (Foo*) fooPtr;

    while ( 1 )
    {
        if ( fooPointer->active() )
        {
            fooPointer->lockMutex();
            /* some code, involving fooPointer */
            fooPointer->unlockMutex();
        }
        else
        {
            pthread_exit ( NULL );
        }
    }

    // somewhere else in the code
    fooPointer->setActive(false);
}

Foo :: setActive(true)は、コンストラクターで呼び出すか、オブジェクトの作成時に呼び出す必要があります。また、スレッドが停止したら、おそらくpthread_join()が完了した後、Fooオブジェクトを削除する必要があります。

于 2012-09-17T08:50:07.827 に答える
-1

c ++オブジェクトがステップブローによって破壊されるため、投稿されたコードは正しくありません。

obj->Foo::~Foo();

free memory //maybe delete if allocated by new

したがって、ソースはデストラクタをプロトエクトしているだけで、メモリ自体は解放されていません。

たぶん、以下のソースコードがあなたを助けるかもしれません、それは単純で粗雑ですが、私はそれがうまくいくと思います

    class Foo 
    {

       public:
         void dosomething() {}
    };

    template<typename T>
    class Protect
    {   
    public: 
        struct auto_lock {
            auto_lock(pthread_mutex_t& mutex)
                : _mutex(mutex)
            {
                pthread_mutex_lock ( &_mutex );
            }
            ~ auto_lock() 
            {
                pthread_mutex_unlock ( &_mutex );
            }
            pthread_mutex_t& _mutex;
        };

        Protect(T*& p): _p(p) {}
        T* get() { return _p; }

        void lock() { pthread_mutex_lock ( &_mutex ); }
        void unlock() { pthread_mutex_unlock ( &_mutex );}
        pthread_mutex_t& getlock() { return _mutex; }

        void safe_release() { 
            auto_lock l(_mutex);
            if (_p != NULL)  {
                delete _p;
                _p = NULL;
            }
        }
    private:
        T*& _p;
        pthread_mutex_t _mutex;
    };

void* thread ( void* proPtr )
{
    Protect<Foo>* proPointer = (Protect<Foo>*) proPtr;

    while ( 1 )
    {
        Protect<Foo>::auto_lock l(proPointer->getlock());
        Foo* fooPtr = proPointer->get();
        if ( fooPtr )
        {
            fooPtr->dosomething();
        }
        else
        {
            pthread_exit ( NULL );
        }
    }
}
于 2012-09-17T09:20:02.570 に答える