https://www.youtube.com/user/BoQianTheProgrammer動画のURL
ユニークなロック
unique_lockのと同様のlock_guard、彼らはラッパークラスのミューテックスですが、前者はより柔軟です
- lock_guard方法のロックを解除しない、unique_lockのアンロックを呼び出すことができます
- unique_lockのではないlock_guard、遅延ロックメソッドを呼び出すことができます
- unique_lockの、コピーすることが移動することができ、lock_guard取り外しできないコピーされないではありません
// 1
...
std::unique_lock<std::mutex> locker(mu);
g_num ++;
locker.unlock();
...
// 2
...
std::unique_lock<std::mutex> locker(mu, std::defer_lock);
...
locker.lock();
g_num++;
locker.unlock();
...
locker.lock();
g_num++;
locker.unlock();
...
// 3
...
std::unique_lock<std::mutex> locker2 = std::move(locker);
unique_lockのlock_guard置換されていません
unique_lockの柔軟性が大きくなるの独自のシェアながら、コスト、柔軟なスペースに来て(オンタイムのパフォーマンスを理解していない)
、時には限り、あなたはlock_guardできるよう、柔軟性のものとunique_lockの必要はありません
Lasy初期化
以下のコードを見てください
class LogFile {
std::mutex _mu;
ofstream _f;
public:
LogFile() {
_f.open("log.txt");
}
void func(string id, int v) {
std::unique_lock<mutex> locker(_mu);
_f << id << ", " << v << endl;
}
}
コンストラクタのlog.txtでオープンクラスの印刷ログ、
しかし、印刷された雑誌を(FUNCを呼び出す)があったことがないこと、そして_f.open呼び出す必要はありません
、次のようにFUNCに_f.open呼び出し考えるには、
class LogFile {
std::mutex _mu;
ofstream _f;
public:
LogFile() {
// _f.open("log.txt");
}
void func(string id, int v) {
if (!_f.is_open()) {
_f.open("log.txt");
}
std::unique_lock<mutex> locker(_mu);
_f << id << ", " << v << endl;
}
}
スレッドセーフ
その後、ログファイルのセキュリティスレッドを考慮する必要があります:: FUNC(リソースが_fオブジェクト用))、従来の方法に従って、ミューテックスで使用_fを制御します
class LogFile {
std::mutex _mu_open;
ofstream _f;
public:
LogFile() { }
void func(string id, int v) {
if (!_f.is_open()) {
std::unique_lock<mutex> locker(_mu_open);
_f.open("log.txt");
}
...
}
}
上記のコードは、スレッドセーフではありません。シナリオは想定しています
、スレッドAとスレッドBを同時にしif (_f.is_open())
、そのファイルが判断を通じ、ので、もし、開いていない
その後、A、Bは、ミューテックスは、開いているファイルを開くには、最初に取得し、コールを想定取得呼び出しますし、その後解放しますミューテックス、
そしてBは、ミューテックスを取得し、その後オープン再び呼び出されます。
ファイルを開くことが二回!
だから、同期する必要_f.openだけでなく、_f.is_openも同期させる必要がある、考えるのは簡単です:
...
std::unique_lock<mutex> locker2(_mu_open);
if (_f.is_open()) {
_f.open("log.txt");
}
locker2.unlock();
...
しかし、別の問題、この時とがあるでしょう、関数が呼び出されるたびに、FUNC、ミューテックス獲得行動をある程度プログラムの同時実行に影響を与えますが存在します
std :: once_flag和のstd ::なcall_once
上記その質問については、C ++は解決するのstd :: once_flag提供しています。
class LogFile {
std::once_flag _flag;
ofstream _f;
public:
LogFile() { }
void func(string id, int v) {
std::call_once(_flag, [&](){_f.open("log.txt");});
...
}
}
ラムダ関数の上記のコードは一度だけ呼び出されたスレッドです!