从多个线程对共享对象的同步方法调用
Synchronizing method calls on shared object from multiple threads
我正在考虑如何实现一个将包含私人数据最终通过方法调用来修改的私有数据的类。对于同步(使用Windows API),我计划使用CRITICAL_SECTION
对象,因为所有线程都将从同一过程中产生。
给定以下设计,我有几个问题。
template <typename T> class Shareable
{
private:
const LPCRITICAL_SECTION sync; //Can be read and used by multiple threads
T *data;
public:
Shareable(LPCRITICAL_SECTION cs, unsigned elems) : sync{cs}, data{new T[elems]} { }
~Shareable() { delete[] data; }
void sharedModify(unsigned index, T &datum) //<-- Can this be validly called
//by multiple threads with synchronization being implicit?
{
EnterCriticalSection(sync);
/*
The critical section of code involving reads & writes to 'data'
*/
LeaveCriticalSection(sync);
}
};
// Somewhere else ...
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
Shareable<ActualType> *ptr = static_cast<Shareable<ActualType>*>(lpParameter);
T copyable = /* initialization */;
ptr->sharedModify(validIndex, copyable); //<-- OK, synchronized?
return 0;
}
我看到的方式将在当前线程的上下文中进行API调用。也就是说,我认为这就像我从指针中获取了关键部分对象,并从ThreadProc()
中称为API。但是,我担心如果对象是创建对象并将其放置在主/初始线程中,那么API调用会时髦。
- 当
sharedModify()
在同一对象上称为同时称为从多个线程中,同步将是隐式的吗我上面描述了它? - 我应该得到一个指针关键部分对象并使用它?
- 还有其他更适合这种情况的同步机制?
当共享modify()在同一对象上同时调用,从多个线程中,同步是否是隐含的,以我上面描述的方式?
这不是隐含的,它是明确的。只有CRITICAL_SECTION
,一次只能容纳一个线程。
我应该得到一个指向关键部分对象的指针并使用它吗?
否。没有理由在这里使用指针。
是否还有其他一些同步机制更适合这种情况?
很难不看到更多代码,但这绝对是"默认"解决方案。这就像一个单连锁的列表 - 您首先学习,它总是有效的,但并不总是最好的选择。
当同一对象上的
sharedModify()
在同一对象上称为,从多个线程中,同步会隐含,以我上面的描述?
从呼叫者的角度隐含的,是的。
我应该得到一个指向关键部分对象的指针并使用它吗?
否。实际上,我建议给出Sharable
的对象所有权,而不是从外部接受一个(并接受Raii概念来编写更安全的代码),例如:
template <typename T>
class Shareable
{
private:
CRITICAL_SECTION sync;
std::vector<T> data;
struct SyncLocker
{
CRITICAL_SECTION &sync;
SyncLocker(CRITICAL_SECTION &cs) : sync(cs) { EnterCriticalSection(&sync); }
~SyncLocker() { LeaveCriticalSection(&sync); }
}
public:
Shareable(unsigned elems) : data(elems)
{
InitializeCriticalSection(&sync);
}
Shareable(const Shareable&) = delete;
Shareable(Shareable&&) = delete;
~Shareable()
{
{
SyncLocker lock(sync);
data.clear();
}
DeleteCriticalSection(&sync);
}
void sharedModify(unsigned index, const T &datum)
{
SyncLocker lock(sync);
data[index] = datum;
}
Shareable& operator=(const Shareable&) = delete;
Shareable& operator=(Shareable&&) = delete;
};
是否还有其他一些同步机制更适合这种情况?
取决于。多个线程会同时访问相同索引吗?如果没有,那么根本不需要关键部分。一个线程可以安全访问一个索引,而另一线程访问不同的索引。
如果多个线程需要同时访问相同的索引,则关键部分可能仍然不是最佳选择。如果您只需要一次锁定部分,则锁定整个阵列可能是一个很大的瓶颈。诸如互锁的API或细长的读/写锁之类的东西可能更有意义。这确实取决于您的线程设计以及您实际试图保护的内容。
- 当我调用对象的方法时,对象的成员会发生变化
- 对类中的对象使用方法
- 在 C++ 的 Switch Case 中创建对象后对对象调用方法
- 为什么按值返回的对象与方法中的对象具有相同的地址?
- 唯一 ptr 将所有权移动到包含对象的方法
- 如何调用从 QML 中C++创建的对象的方法?
- C++对象本身作为参数调用对象的方法
- C++:访问对象内部子对象的方法
- 如何在 VC++ 中通过引用传递另一个对象的方法(错误 C2664)
- 如何使用函数指针调用对象的方法?
- C++对象构造方法之间的差异
- 从矢量中删除对象的方法?
- 从成员对象调用方法
- CPU寄存器中返回的用户定义类型的C 对象.实例方法如何工作
- 处理C 中对象的方法
- 调用对象类方法,该方法在另一个对象类中的向量中
- c++ 将 vector<Parent*> 的元素传递到需要 chidren 的对象的方法中
- Qt的GUI线程在从外部对象调用方法时是否会在引擎盖下生成线程?
- LLDB API:如何调用存储在SBValue中的对象的方法
- 从多个线程对共享对象的同步方法调用