mac*_*mac 31 c++ mutex c++11 stdthread
我最近实现线程/互斥管理器的努力最终导致75%的CPU负载(4核心),而所有四个正在运行的线程都处于睡眠状态或等待互斥锁解锁.
具体的类太大了,不能完全发布在这里,但我可以把原因缩小到两个互斥锁的死锁安全获取
std::unique_lock<std::mutex> lock1( mutex1, std::defer_lock );
std::unique_lock<std::mutex> lock2( mutex2, std::defer_lock );
std::lock( lock1, lock2 );
Run Code Online (Sandbox Code Playgroud)
该类的另一部分使用std::condition_variable
with wait()
和notify_one()
on mutex1
来同时有选择地执行某些代码.
简单的改变
std::unique_lock<std::mutex> lock1( mutex1 );
std::unique_lock<std::mutex> lock2( mutex2 );
Run Code Online (Sandbox Code Playgroud)
使CPU使用率降至正常的1-2%.
我不敢相信,std::lock()
功能是低效的.这可能是g ++ 4.6.3中的错误吗?
编辑:(示例)
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
std::mutex mutex1, mutex2;
std::condition_variable cond_var;
bool cond = false;
std::atomic<bool>done{false};
using namespace std::chrono_literals;
void Take_Locks()
{
while( !done )
{
std::this_thread::sleep_for( 1s );
std::unique_lock<std::mutex> lock1( mutex1, std::defer_lock );
std::unique_lock<std::mutex> lock2( mutex2, std::defer_lock );
std::lock( lock1, lock2 );
std::this_thread::sleep_for( 1s );
lock1.unlock();
lock2.unlock();
}
}
void Conditional_Code()
{
std::unique_lock<std::mutex> lock1( mutex1, std::defer_lock );
std::unique_lock<std::mutex> lock2( mutex2, std::defer_lock );
std::lock( lock1, lock2 );
std::cout << "t4: waiting \n";
while( !cond )
cond_var.wait( lock1 );
std::cout << "t4: condition met \n";
}
int main()
{
std::thread t1( Take_Locks ), t2( Take_Locks ), t3( Take_Locks );
std::thread t4( Conditional_Code );
std::cout << "threads started \n";
std::this_thread::sleep_for( 10s );
std::unique_lock<std::mutex> lock1( mutex1 );
std::cout << "mutex1 locked \n" ;
std::this_thread::sleep_for( 5s );
std::cout << "setting condition/notify \n";
cond = true;
cond_var.notify_one();
std::this_thread::sleep_for( 5s );
lock1.unlock();
std::cout << "mutex1 unlocked \n";
std::this_thread::sleep_for( 6s );
done = true;
t4.join(); t3.join(); t2.join(); t1.join();
}
Run Code Online (Sandbox Code Playgroud)
How*_*ant 26
在我的机器上,以下代码每秒打印10次并消耗几乎0 cpu,因为大多数情况下线程在锁定的互斥锁上处于休眠或阻塞状态:
#include <chrono>
#include <thread>
#include <mutex>
#include <iostream>
using namespace std::chrono_literals;
std::mutex m1;
std::mutex m2;
void
f1()
{
while (true)
{
std::unique_lock<std::mutex> l1(m1, std::defer_lock);
std::unique_lock<std::mutex> l2(m2, std::defer_lock);
std::lock(l1, l2);
std::cout << "f1 has the two locks\n";
std::this_thread::sleep_for(100ms);
}
}
void
f2()
{
while (true)
{
std::unique_lock<std::mutex> l2(m2, std::defer_lock);
std::unique_lock<std::mutex> l1(m1, std::defer_lock);
std::lock(l2, l1);
std::cout << "f2 has the two locks\n";
std::this_thread::sleep_for(100ms);
}
}
int main()
{
std::thread t1(f1);
std::thread t2(f2);
t1.join();
t2.join();
}
Run Code Online (Sandbox Code Playgroud)
样本输出:
f1 has the two locks
f2 has the two locks
f1 has the two locks
...
Run Code Online (Sandbox Code Playgroud)
我在OS X上运行它,并且Activity Monitor应用程序说这个过程使用0.1%cpu.该机器是英特尔酷睿i5(4核).
我很乐意以任何方式调整此实验以尝试创建实时锁定或过多的CPU使用.
更新
如果此程序在您的平台上使用过多的CPU,请尝试将其更改为调用::lock()
,其中定义为:
template <class L0, class L1>
void
lock(L0& l0, L1& l1)
{
while (true)
{
{
std::unique_lock<L0> u0(l0);
if (l1.try_lock())
{
u0.release();
break;
}
}
std::this_thread::yield();
{
std::unique_lock<L1> u1(l1);
if (l0.try_lock())
{
u1.release();
break;
}
}
std::this_thread::yield();
}
}
Run Code Online (Sandbox Code Playgroud)
我很想知道这对你有什么影响,谢谢.
更新2
经过长时间的拖延,我写了一篇关于这个主题的论文初稿.本文比较了完成这项工作的4种不同方式.它包含可以复制并粘贴到您自己的代码中并自行测试的软件(请报告您找到的内容!):
http://howardhinnant.github.io/dining_philosophers.html
如文档所述,对象是通过一系列未指定的锁定,try_lock和unlock的调用来锁定的。如果互斥锁在相当长的一段时间内被其他线程保持,则根本没有办法可能会有效。该函数无法等待而不会旋转。
归档时间: |
|
查看次数: |
7393 次 |
最近记录: |