实现文件写入的互斥锁

我试图使用互斥锁来避免多次写入C / Cpp中的同一个线程。 以下是我的程序流程。 我很困惑在哪里包括我的锁和解锁代码。

main() { spawn a worker thread } worker_thread() { read the input file name read some content write the content to the given file name } 

我看到的大部分实现似乎都是这样的:

 main() { pthread_mutex_init(&myMutex;,0); *spawn a worker thread* pthread_join(thread1, 0); pthread_mutex_destroy(&myMutex;); } worker_thread() { read the input file name read some content write the content to the given file name } 

我想要的是这样的:

 main() { spawn a worker thread } worker_thread() { read the input file name read some content pthread_mutex_init(&myMutex;,0) --> for the given file? write the content to the given file name pthread_mutex_destroy(&myMutex;); } 

任何想要继续欣赏的想法。 谢谢!

为iostream创建一个包装器相当容易,确保一次只能有一个线程写入流。 不幸的是,几乎一旦你这样做,你就会遇到另一个问题。 它确保一次只能有一个线程插入到流中,因此您可以获得已定义的行为。 但是,如果你有类似的东西:

线程1: sync_stream << a << b << c << '\n';
线程2: sync_stream << x << y << z << '\n';

你想要的是:

ABC
XYZ

...要不然:

XYZ
ABC

由于它们位于不同的线程中,因此它们之间的顺序变化很好,但是一个线程的输出行应保持单行输出。 就像是:

ABXY
CZ

......可能不是不可取或不可接受的。 为了避免这种情况,我们确实需要两个单独的类。 一个是同步流。 另一个是让我们在流中作为单个不可分割的“事务”进行一些(或多或少任意)插入的集合。 为此,我们可以使用这样的一对类:

 class transaction { std::ostringstream buffer; public: transaction(std::string const &s="") : buffer(s, std::ios::out | std::ios::ate) {} template  transaction &operator<<(T const &t) { buffer << t; return *this; } friend std::ostream &operator<<(std::ostream &os, transaction const &t) { return os << t.buffer.str(); } }; class sync_stream { std::ostream &out; std::mutex mutex; public: sync_stream(std::ostream &sink) : out(sink) { } void operator<<(transaction const &t) { std::lock_guard l(mutex); out << t; } }; 

请注意, transaction类支持链接,但sync_stream不支持(并且您可以插入的唯一transactiontransaction )。 要使用它们,我们会这样做:

 for (int i=0; i<10; i++) threads[i] = std::thread([&]{ for (int i=0; i<10; i++) s << (transaction() << "Thread: " << std::this_thread::get_id() << "\n"); }); 

这样,线程认为单个输出实际上是单个输出,所以我们的结果可能如下所示:

线程:140375947724544
线程:140376068564736
线程:140375964509952
线程:140375964509952
线程:140375972902656
线程:140375964509952

当然,你会获得与我不同的线程ID,并且线的顺序可能会有所不同 - 但每一行都将被写为一个完整的单一单元。

摘要

工作线程根本不应该直接与互斥锁一起工作。 这应该是自动化的,因此工作者线程可以专注于其工作,并且只花费最少的努力来完成其工作所需的底层机制。