在c++中不正确地使用互斥锁
Using mutex locks incorrectly in C++ somehow
我有以下代码来尝试(和失败)保护我的代码中的关键区域。基本上,我希望在其他线程打印另一条语句之前,任何线程都能完全执行一条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::cout
和printf
不是最好的主意。
这是个有趣的问题。我不认为这解决了根本问题(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
}
- 如何正确地将分支添加到已存在的树中
- 如何正确地将带有指针的数组传递给函数
- 如何正确地推回然后遍历堆中对象的向量?
- 我是否不正确地集中了这些字符数组?
- 如何通过另一个对象中的命令正确地从一个对象返回数据
- 我怎样才能通过友谊正确地履行我的职能?
- C++:如何正确地将 deque::front() 返回的变量从函数中传递出去?
- 我应该如何正确地将packaged_task移动到 lambda?
- 如何正确地将SHA1CryptoServiceProvider转换为c ++?
- 如何正确地对 constexpr 函数进行单元测试
- 我的动态链接队列在同一输出流中调用时不正确地输出三个返回函数
- 如何正确地将boost::asio::buffers_iterator转换为InputIterator
- 如何正确地检查变量char中包含的字母
- 当试图交换可变模板类时,如何正确地重载operator=
- 如何正确地将 boost::optional<std::chrono::d uration> 作为函数参数?
- 如何在C++中正确地将我的语言字符输出到HTML文件中
- 如果我的类正确地管理了一个资源,那么拥有智能的poointer有什么意义
- 如何正确地编写这些条件,以便它们在控制台中工作
- 正确地编写一个类,并将pthread与vlc库和c++一起使用
- 如何正确地从函数 (type_traits) 给出向量