我的问题是,我有多个线程更新的块矩阵。 多个线程可能一次更新不相交的块,但通常可能存在竞争条件。现在矩阵使用单锁锁定。
问题是,是否可能(如果是的话,怎么样?) 实现一个有效的锁定数组,以便一次只能锁定矩阵的一部分。
有问题的矩阵可以变得相当大,按照50 ^ 2块的顺序。我最初的猜测是使用动态分配互斥量的矢量/映射。
这是好方法吗? 是否更好地使用多个条件变量? 有更好的方法吗?
答案 0 :(得分:6)
使用单个锁。但是,不是使用它来保护整个矩阵,而是使用它来保护std::set
(或boost::unordered_set
),它表示哪些块被“锁定”。
像这样。
class Block;
class Lock_block
{
public:
Lock_block( Block& block ) : m_block(&block)
{
boost::unique_lock<boost::mutex> lock(s_mutex);
while( s_locked.find(m_block) != s_locked.end() )
{
s_cond.wait(lock);
}
bool success = s_locked.insert(m_block).second;
assert(success);
}
~Lock_block()
{
boost::lock_guard<boost::mutex> lock(s_mutex);
std::size_t removed = s_locked.erase(m_block);
assert(removed == 1);
s_cond.notify_all();
}
private:
Block* m_block;
static boost::mutex s_mutex;
static boost::condition s_cond;
static std::set<Block*> s_locked;
};
答案 1 :(得分:1)
您可以使用以下几种方法:
如果CriticalSection / Mutexes(2500不是那么多)预先分配数组,并使用块索引作为锁索引来收集块访问;在更新块之前锁定要更改的所有块;做更新;解锁;
如果计算时间明显长于锁定/解锁,则在线程上下文中复制块的内容并在此期间保持块解锁;在更新块之前再次锁定它并确保它没有被另一个线程更新(如果它与此相关);如果它被另一个线程更新,则重复操作;
如果块内容的大小很小,则使用原子数据交换来更新块内容,不需要锁定;只是不确定你是否使用一个块中的数据来计算另一个块的数据,在这种情况下锁定所需的所有更新块;
矩阵上有读取操作吗?如果是,请使用读/写锁来提高性能。