在c++中不正确地使用互斥锁

Using mutex locks incorrectly in C++ somehow

本文关键字:正确地 c++ 不正确      更新时间:2023-10-16

我有以下代码来尝试(和失败)保护我的代码中的关键区域。基本上,我希望在其他线程打印另一条语句之前,任何线程都能完全执行一条print语句。

In main.h:

pthread_mutex_t printer_mutex;

main.c -程序做的第一件事:

pthread_mutex_init(&printer_mutex, NULL);

线程是这样创建的(我已经删除了一些检查):

for(long t = 0; t < NUM_THREADS; t++) {
   args[t].fw = fw;
   args[t].deriv_init = deriv_init;
   args[t].to_prove = fw.to_prove.at(i);
   pthread_create(&threads[t], NULL, do_derivation_helper, (void *) &args[t]);
}
for(long t = 0; t < NUM_THREADS; t++) {
  pthread_join(threads[t], NULL);
}

然后在我的一个类中执行程序中的所有打印,我有以下内容。打印应锁定,打印完成后再解锁。

void InfoViewer::rule_x_fires() {
    // START CRITICAL REGION
    pthread_mutex_lock(&printer_mutex);
    cout << "INFO: Rule x fires" << endl;
    pthread_mutex_unlock(&printer_mutex);
    // END CRITICAL REGION
}
我得到的不想要的输出是:
INFO: Rule x firesINFO: Rule x fires

。在其他线程开始打印之前,该行没有结束。

任何想法?我没有正确初始化吗?我可以在我的c++程序中使用标准的C风格线程吗?

我认为问题在于在头文件中定义互斥变量。这样,每个编译单元都有自己版本的这种变量,您只需锁定不同的互斥锁。只需这样做:

// .h header file: declare
extern pthread_mutex_t printer_mutex;
// one of the .c/.cpp files: define
pthread_mutex_t printer_mutex;

编辑0:

解释为什么它可以在多个定义下"工作"——PThread互斥锁可以用两种不同的方式初始化——用pthread_mutex_init动态初始化,用PTHREAD_MUTEX_INITIALIZER静态初始化。查看pthread.h,可以找到以下内容(32位版本):

# define PTHREAD_MUTEX_INITIALIZER 
    { { 0, 0, 0, 0, 0, { 0 } } }

这意味着任何pthread_mutex_t类型的静态变量都将被正确初始化,而无需显式赋值,或者由于静态内存为零填充而进行初始化调用。因此,您显式地动态初始化了一个互斥锁,所有其他互斥锁都被隐式地初始化为全0。

您始终可以将std::cout的使用更改为printf()。你在Mac上,一个posix兼容的操作系统。printf()保证是原子的。实际上,如果您可以使用printf,那么一次产生的所有输出都由单个printf()调用执行,那么您甚至不应该需要互斥锁。std::cout没有任何保证。没有。

如果您将std::cout的这种特殊用法转换为printf,您应该在整个应用程序中进行此操作。混合std::coutprintf不是最好的主意。

这是个有趣的问题。我不认为这解决了根本问题(ostream中的同步),但试试这个:

void InfoViewer::rule_x_fires() {
    // START CRITICAL REGION
    pthread_mutex_lock(&printer_mutex);
    cout << "INFO: Rule x fires" << endl;
    cout.flush();
    pthread_mutex_unlock(&printer_mutex);
    // END CRITICAL REGION
}