ブーストなどの最新の C++ スレッド ライブラリにアクセスできないプロジェクト用に、次のコードを作成しました。私の望みは、ロックがスコープを離れたときに自動的にロックを解除できるようにすることです。
共有ロックは正常に機能します。スレッドがそれを取得すると、最初のスレッドがそれを解放するまで、それを取得することはできません。ただし、Scoped は機能しません。
ここに、私が何を意味するかを示す出力があります。各スレッドに個別の名前を付け、同じ共有ロックでスコープ ロックをインスタンス化し、「取得済み」と出力し、5 秒間スリープし、「解放済み」と出力してから、スコープを離れました。私が期待する取得/解放のペアを取得する代わりに、4 つの「取得済み」が立て続けに取得され、5 秒のギャップがあり、次に「解放済み」が取得されます。私は Scoped のロックをポインターに変更し、取得する前にアドレスを出力しました。同じ Shared オブジェクトのように見えますが、ロックは複数のアクセスを妨げていません。
Lock '140734928395200'.
acquired: !!!!!
Lock '140734928395200'.
acquired: -------
Lock '140734928395200'.
acquired: ***************
Lock '140734928395200'.
acquired: ##
released: !!!!!
released: -------
released: ***************
released: ##
Lock.h のソース コードは次のとおりです。
#include <pthread.h>
namespace Lock
{
class Shared
{
public:
Shared()
{
::pthread_mutex_init(&(this->mutex), nullptr);
}
~Shared()
{
}
void acquire()
{
::pthread_mutex_lock(&(this->mutex));
}
void release()
{
::pthread_mutex_unlock(&(this->mutex));
}
private:
pthread_mutex_t mutex;
};
class Scoped
{
public:
Scoped(Lock::Shared& lock) : lock(lock)
{
this->lock.acquire();
}
virtual ~Scoped()
{
this->lock.release();
}
private:
Lock::Shared& lock;
};
};
これがテスト用の私の main.cc ファイルです。私は以下で構築しています:
g++ -std=c++11 -o try -pthread main.cc && ./try
最新のUbuntuシステムでg ++ 4.7を使用。
#include <pthread.h>
#include <iostream>
#include "Lock.h"
#include <unistd.h>
struct data
{
data(std::string name, Lock::Shared& lock) : name(name), lock(lock) { ; }
std::string name;
Lock::Shared& lock;
};
void* doStuff(void* v)
{
data* d = (data*)v;
for (int i = 0; i < 5; i++)
{
Lock::Scoped(d->lock);
//d->lock->acquire();
std::cout << "acquired: " << d->name << std::endl;
::sleep(5);
std::cout << "released: " << d->name << std::endl;
//d->lock->release();
::sleep(1);
}
}
int main(int argc, char* argv[])
{
pthread_t fred;
pthread_t barney;
pthread_t wilma;
pthread_t betty;
Lock::Shared lock;
data f("##", lock);
data b("***************", lock);
data w("-------", lock);
data e("!!!!!", lock);
::pthread_create(&fred, nullptr, doStuff, (void*)&f);
::pthread_create(&barney, nullptr, doStuff, (void*)&b);
::pthread_create(&wilma, nullptr, doStuff, (void*)&w);
::pthread_create(&betty, nullptr, doStuff, (void*)&e);
::pthread_join(fred, nullptr);
::pthread_join(barney, nullptr);
::pthread_join(wilma, nullptr);
::pthread_join(betty, nullptr);
return 0;
}