我有一个包含两个函数 func1 和 func2 的代码。两者作用的作用是一样的。不断读取目录并写入各自日志文件中存在的文件名。这两个函数都引用了一个通用的日志函数来写入日志。我想在我的代码中使用引入线程,这样它们都可以继续并行运行,但两者都不应该同时访问日志函数。如何做到这一点?
6 回答
这是需要互斥锁的经典案例。
void WriteToLog(const char *msg)
{
acquire(mutex);
logfile << msg << endl;
release(mutex);
}
上面的代码不会“复制并粘贴”到您的系统中,因为互斥锁是系统特定pthread_mutex
的 - 如果您使用pthreads
. C++11 有它自己的互斥锁和线程功能,而 Windows 有另一个变体。
来自 Sajal 的评论:
试过 pthread_create(&thread1, NULL, start_opca, &opca); pthread_join(thread1, NULL); pthread_create(&thread2, NULL, start_ggca, &ggca); pthread_join(thread2, NULL);
但是这样做的问题是它会等待一个线程完成,然后再开始下一个线程。我不想要那个。
join 函数阻塞调用线程,直到你调用 join 的线程完成。在您的情况下,在创建第二个线程之前在第一个线程上调用 join 可以保证第一个线程将在第二个线程开始之前结束。
您应该首先创建两个线程,然后将它们都连接起来(而不是穿插两者的创建和连接)。
此外,对日志的访问应该被提取到两者的通用代码中(一个日志函数、一个日志类等。在提取的代码中,应该使用互斥锁来保护日志访问。
如果你有一个(部分)支持 c++11 的实现,你应该为此使用 std::thread 和 std::mutex 。否则,您应该使用 boost::thread。如果您都无法访问,请在 linux 下使用 pthreads。
在 linux 上,您将需要使用pthreads
由于两个线程都在从/向 I/O 读取/写入(读取 dirs 和写入日志文件),因此不需要多线程:由于每个 I/O 访问都在较低级别排队,因此并行化任务不会提高速度。
此 C 语言代码可能会给您一些提示。回答您的问题: 您应该在 pthread 中使用 mutex 以确保日志文件只能由一个线程同时访问。
#include <pthread.h>
#include <stdio.h>
pthread_mutex_t LogLock = PTHREAD_MUTEX_INITIALIZER;
char* LogFileName= "test.log";
void* func_tid0( void* a) {
int i;
for(i=0; i < 50; i++ ) {
pthread_mutex_lock(&LogLock);
fprintf((FILE*)a, "write to log by thread0:%d\n", i);
pthread_mutex_unlock(&LogLock);
}
}
void* func_tid1(void* a) {
int i;
for(i=0; i < 50; i++ ) {
pthread_mutex_lock(&LogLock);
fprintf((FILE*)a, "write to log by thread1:%d\n", i);
pthread_mutex_unlock(&LogLock);
}
}
int main() {
pthread_t tid0, tid1;
FILE* fp=fopen(LogFileName, "wb+");
pthread_create(&tid0, NULL, func_tid0, (void*) fp );
pthread_create(&tid1, NULL, func_tid1, (void*) fp );
void* ret;
pthread_join(tid0, &ret);
pthread_join(tid1, &ret);
}
你的另一个问题不存在。因为主线程在您的第一个 pthread_join 处暂停,但这并不意味着第二个线程不运行。实际上第二个线程从 pthread_create(thread1) 开始。
实际上 pthread_mutex 会导致您的程序串行。