C++のshared_timed_mutexを使用して、reader-writersの問題の実装を記述しました。私の意見では、次のコードは、あまりにも多くのリーダースレッドがデータベース(この例では単純な配列)で常に作業しているため、ライターが飢えてしまう原因となるはずです:ライターはロックを取得する機会がありません。ライタースレッドが飢えさせる方法
mutex cout_mtx; // controls access to standard output
shared_timed_mutex db_mtx; // controls access to data_base
int data_base[] = { 0, 0, 0, 0, 0, 0 };
const static int NR_THREADS_READ = 10;
const static int NR_THREADS_WRITE = 1;
const static int SLEEP_MIN = 10;
const static int SLEEP_MAX = 20;
void read_database(int thread_nr) {
shared_lock<shared_timed_mutex> lck(db_mtx, defer_lock); // create a lock based on db_mtx but don't try to acquire the mutex yet
while (true) {
// generate new random numbers
std::random_device r;
std::default_random_engine e(r());
std::uniform_int_distribution<int> uniform_dist(SLEEP_MIN, SLEEP_MAX);
std::uniform_int_distribution<int> uniform_dist2(0, 5);
int sleep_duration = uniform_dist(e); // time to sleep between read requests
int read_duration = uniform_dist(e); // duration of reading from data_base
int cell_number = uniform_dist2(e); // what data cell will be read from
int cell_value = 0;
// wait some time before requesting another access to the database
this_thread::sleep_for(std::chrono::milliseconds(sleep_duration));
if (!lck.try_lock()) {
lck.lock(); // try to get the lock in blocked state
}
// read data
cell_value = data_base[cell_number];
lck.unlock();
}
}
void write_database(int thread_nr) {
unique_lock<shared_timed_mutex> lck(db_mtx, defer_lock); // create a lock based on db_mtx but don't try to acquire the mutex yet
while (true) {
// generate new random numbers
std::random_device r;
std::default_random_engine e(r());
std::uniform_int_distribution<int> uniform_dist(SLEEP_MIN, SLEEP_MAX);
std::uniform_int_distribution<int> uniform_dist2(0, 5);
int sleep_duration = uniform_dist(e); // time to sleep between write requests
int read_duration = uniform_dist(e); // duration of writing to data_base
int cell_number = uniform_dist2(e); // what data cell will be written to
// wait some time before requesting another access to the database
this_thread::sleep_for(std::chrono::milliseconds(sleep_duration));
// try to get exclusive access
cout_mtx.lock();
cout << "Writer <" << thread_nr << "> requesting write access." << endl;
cout_mtx.unlock();
if (!lck.try_lock()) {
lck.lock(); // try to get the lock in blocked state
}
// write data
data_base[cell_number] += 1;
lck.unlock();
}
}
スレッドが読んでいるとき、私はブロックされたモードまたはtry_lock()
方法のいずれかを介してロックを取得しようとすると、書き込み、標準出力にいくつかの出力を追加しましたが、私は明確化のために出力を削除しました。メインメソッドでスレッドをさらに開始します。私がプログラムを実行すると、ライターは常に配列に書き込む機会を得ます(読者のスレッドはすべてブロックされますが、これは大丈夫です)。しかし、上記のように、ライターはアクセス権を得ることができないはずです配列から読み取る多くのリーダースレッド読者のスレッドをまったくスリープ状態にしていなくても(引数0)、ライタースレッドは何とかmutexを取得する方法を見つけます。どのようにして作家に飢えさせるのですか?
あなたはどちらのstd :: libを使用していますか? –
@HowardHinnantはちょうどC++ 11月14日内部同期メカニズム: –
kimsay
ああ、私はGCCののlibstdC++を思っていた、VS、libcの++?重要ではなく、ただ好奇心が強い。 –