スレッドと排他処理
c++のスレッドの練習がてらスレッドを使ったファイル出力をやってみた。
#include <thread> #include <fstream> #include <iostream> void ThreadA() { std::string filename = "test.txt"; std::ofstream writing_file; writing_file.open(filename, std::ios::out | std::ios::app); for (int i=0; i < 100000; i++) writing_file << 'A'; } void ThreadB() { std::string filename = "test.txt"; std::ofstream writing_file; writing_file.open(filename, std::ios::out || std::ios::app || std::ios::trunc); for (int i = 0; i < 100000; i++) writing_file << 'B'; } int main() { std::thread th_a(ThreadA); std::thread th_b(ThreadB); std::thread th_c([]() { std::string filename = "test.txt"; std::ofstream writing_file; writing_file.open(filename, std::ios::out || std::ios::app || std::ios::trunc); for (int i = 0; i < 100000; i++) writing_file << 'C'; }); th_a.join(); th_b.join(); th_c.join(); return 0; }
ファイル出力でやってみた
#include <thread> #include <fstream> #include <mutex> std::mutex mtx; void write(char c) { //std::lock_guard<std::mutex> lock(mtx); std::string filename = "./test.txt"; std::ofstream writing_file; writing_file.open(filename, std::ios::out | std::ios::app); writing_file << c; } void ThreadA() { for (int i = 0; i < 1000; i++) write('A'); } void ThreadB() { for (int i = 0; i < 1000; i++) write('B'); } void ThreadC() { for (int i = 0; i < 1000; i++) write('C'); } int main() { std::thread th_a(ThreadA); std::thread th_b(ThreadB); std::thread th_c(ThreadC); th_a.join(); th_b.join(); th_c.join(); return 0; }
ファイル出力はとても遅い。終わるのに15秒ほどかかった。
しかも、ファイルに書き込まれるべき文字数は3000文字のはずが2100文字たらずしか書き込まれていなかった。
これは、まさにスレッド特有の問題データ競合 (data races) が起こっている。
次は、排他処理mutexを導入したファイル出力のコード
#include <thread> #include <fstream> #include <mutex> std::mutex mtx; void write(char c) { std::lock_guard<std::mutex> lock(mtx); std::string filename = "./test.txt"; std::ofstream writing_file; writing_file.open(filename, std::ios::out | std::ios::app); writing_file << c; } void ThreadA() { for (int i = 0; i < 1000; i++) write('A'); } void ThreadB() { for (int i = 0; i < 1000; i++) write('B'); } void ThreadC() { for (int i = 0; i < 1000; i++) write('C'); } int main() { std::thread th_a(ThreadA); std::thread th_b(ThreadB); std::thread th_c(ThreadC); th_a.join(); th_b.join(); th_c.join(); return 0; }
時間は大体30秒ほどかかった。ざっと2倍かかってる。
文字数はちゃんと3000文字書きもまれていた。
〇参考サイト
kaworu.jpn.org