【发布时间】:2019-01-10 09:51:15
【问题描述】:
我有一个写入器,它必须以相当高的频率递增一个变量,还有一个或多个读取器以较低的频率访问这个变量。
写入由外部中断触发。
由于我需要高速写入,我不想使用互斥锁或其他昂贵的锁定机制。
我想出的方法是在写入后复制值。读者现在可以将原件与副本进行比较。如果相等,则变量的内容有效。
这是我在 C++ 中的实现
template<typename T>
class SafeValue
{
private:
volatile T _value;
volatile T _valueCheck;
public:
void setValue(T newValue)
{
_value = newValue;
_valueCheck = _value;
}
T getValue()
{
volatile T value;
volatile T valueCheck;
do
{
valueCheck = _valueCheck;
value = _value;
} while(value != valueCheck);
return value;
}
}
这背后的想法是在读取时检测数据竞争,并在发生时重试。但是,我不知道这是否总是有效。我在网上没有找到任何关于这种方法的信息,因此我的问题是:
我的方法与单个作者和多个阅读器一起使用时有什么问题吗?
我已经知道高写入频率可能会导致读者饿死。还有更多的不良影响我必须小心吗?难道这根本就不是线程安全的吗?
编辑 1:
我的目标系统是 ARM Cortex-A15。
T 至少应该能够成为任何原始整数类型。
编辑 2:
std::atomic 在读写器站点上太慢了。我在我的系统上对其进行了基准测试。与未受保护的原始操作相比,写入大约慢 30 倍,读取大约慢 50 倍。
【问题讨论】:
-
评论不用于扩展讨论;这个对话是moved to chat。
-
您真的需要高速写入吗?难道你不能增加一个写入器私有变量,然后定期将它添加到读者可访问的总数中,而不是必须经常将总数增加1吗?换句话说,读者能容忍一点陈旧吗?
-
@Branko Dimitrijevic - 不多。计数器用于跟踪步进电机的位置。读者需要尽可能准确地获取该电机的位置。
-
@Detonar 我建议编辑问题以详细解释为什么原子不适合您。正如您在下面的评论中所写:
std::atomic的问题是内部系统调用大大减慢了它的速度。什么内部系统调用?仅当给定数据类型的硬件支持原子操作时,原子操作才应归结为特殊指令(您的情况是否如此?)。 放慢速度是什么意思?生产者放缓?消费者放缓?你如何衡量这种放缓? -
@Daniel Langr - 我在目标系统上对其进行了基准测试。编辑了我的问题。
标签: c++ multithreading lock-free