C++ 在c+中包含和访问线程全局变量+;
在我去过的几个工作场所中,我发现了一个设计问题,但没有令人满意的解决方案: 假设您有一个具有动态线程数的系统 每个线程必须有一个访问一组“单例”的权限,单例每个线程只有一个实例(因此它们不是真正的单例,而是每个线程的单例) 这组单例在编译时是已知的 每个单例都有一个默认构造函数(不过,为了简化事情,一个没有这个约束的解决方案会更好) 令人满意的解决方案应包括以下内容:C++ 在c+中包含和访问线程全局变量+;,c++,oop,metaprogramming,C++,Oop,Metaprogramming,在我去过的几个工作场所中,我发现了一个设计问题,但没有令人满意的解决方案: 假设您有一个具有动态线程数的系统 每个线程必须有一个访问一组“单例”的权限,单例每个线程只有一个实例(因此它们不是真正的单例,而是每个线程的单例) 这组单例在编译时是已知的 每个单例都有一个默认构造函数(不过,为了简化事情,一个没有这个约束的解决方案会更好) 令人满意的解决方案应包括以下内容: 每个线程都可以在o(1)时间内访问其任何单例 对单例的访问是无锁的 将单例添加到“单例集合”不需要在集合端编写新代码 “单例集”
提前感谢您的任何见解。好的,通常我会在评论中发表这一点,因为我不太确定我是否正确理解了您的问题……但在父线程类的构造函数中创建单例集的实例还不够吗 假设您有三个类A、B和C(在编译时已知) 和一个“线程”类 您不在线程头中声明A、B和C的实例吗
class Thread {
private:
A *a;
B *b;
C *c;
public:
Thread();
}
然后在线程的构造函数中实例化它们
Thread:Thread() {
a = new A();
b = new B();
c = new C();
}
这样,每个线程独占地“拥有”这些单例,这意味着它可以随时访问它们,而不必担心竞争条件或锁
关于“添加单例”,我是否可以建议创建一个“单例父级”类,然后使用一个标准容器(如std::list),您可以将新指针推送到该容器上?
当然,对该列表的访问必须受到锁的保护,当您在运行时、编译时执行此操作时,这是不必要的。
在编译期间,最好使用指针的静态数组,这将允许您尽可能快地访问指针
再一次,如果我理解错了你的问题,我很抱歉。好的,通常我会在评论中发表这篇文章,因为我不太确定我是否正确理解了你的问题……但是在父线程类的构造函数中创建单例集的实例还不够吗 假设您有三个类A、B和C(在编译时已知) 和一个“线程”类 您不在线程头中声明A、B和C的实例吗
class Thread {
private:
A *a;
B *b;
C *c;
public:
Thread();
}
然后在线程的构造函数中实例化它们
Thread:Thread() {
a = new A();
b = new B();
c = new C();
}
这样,每个线程独占地“拥有”这些单例,这意味着它可以随时访问它们,而不必担心竞争条件或锁
关于“添加单例”,我是否可以建议创建一个“单例父级”类,然后使用一个标准容器(如std::list),您可以将新指针推送到该容器上?
当然,对该列表的访问必须受到锁的保护,当您在运行时、编译时执行此操作时,这是不必要的。
在编译期间,最好使用指针的静态数组,这将允许您尽可能快地访问指针
再一次,如果我理解错了您的问题,我很抱歉。线程局部变量很好地解决了这个问题
// in .h
class ThreadSingleton
{
private:
static __thread ThreadSingleton* thread_specific_instance;
public:
static ThreadSingleton* get() { return thread_specific_instance; }
ThreadSingleton();
~ThreadSingleton();
};
// in .cc
__thread ThreadSingleton* ThreadSingleton::thread_specific_instance;
ThreadSingleton::ThreadSingleton() {
if(thread_specific_instance)
std::abort(); // one instance per thread please
thread_specific_instance = this;
}
ThreadSingleton::~ThreadSingleton() {
thread_specific_instance = 0;
}
// usage
int main() {
// on thread entry
ThreadSingleton x;
// later anywhere in the thread
ThreadSingleton* px = ThreadSingleton::get();
}
每个线程在堆栈的某个位置创建ThreadSingleton
,通常在线程函数中。稍后,ThreadSingleton
可以通过返回调用线程的singleton的ThreadSingleton::get()
从该线程的任何位置访问。(上面可以制作一个模板来包装任何其他类,我没有这样做是为了简单的说明)
以性能为导向访问线程局部变量不需要任何调用(与使用创建的线程特定存储不同),有关详细信息,请参阅。线程局部变量很好地解决了这个问题
// in .h
class ThreadSingleton
{
private:
static __thread ThreadSingleton* thread_specific_instance;
public:
static ThreadSingleton* get() { return thread_specific_instance; }
ThreadSingleton();
~ThreadSingleton();
};
// in .cc
__thread ThreadSingleton* ThreadSingleton::thread_specific_instance;
ThreadSingleton::ThreadSingleton() {
if(thread_specific_instance)
std::abort(); // one instance per thread please
thread_specific_instance = this;
}
ThreadSingleton::~ThreadSingleton() {
thread_specific_instance = 0;
}
// usage
int main() {
// on thread entry
ThreadSingleton x;
// later anywhere in the thread
ThreadSingleton* px = ThreadSingleton::get();
}
每个线程在堆栈的某个位置创建ThreadSingleton
,通常在线程函数中。稍后,ThreadSingleton
可以通过返回调用线程的singleton的ThreadSingleton::get()
从该线程的任何位置访问。(上面可以制作一个模板来包装任何其他类,我没有这样做是为了简单的说明)
性能智能访问线程局部变量不需要任何调用(与使用创建的线程特定存储不同),请参阅以了解更多详细信息。我不确定是否正确理解了您的问题,但对我来说,单例的“集”是不相关的。您有固定数量的单例,将它们称为
Singleton1
到SingletonX
,其中X
在编译时已知。这对线程来说并不重要
对于实际的单例,您可以让它们从处理每线程部分的单个模板基类继承。大概是这样的:
template<class B>
struct SingletonBase
{
static B &getInstance()
{
// One instance per thread
static std::unordered_map<std::thread::id, B> intances;
if (instances.find(std::this_thread::get_id()) == instances.end())
instances[std::this_thread::get_id()] = B{};
return instances[std::this_thread::get_id()];
}
};
class Singleton1 : public SingletonBase<Singleton1>
{
// ...
};
这将在编译时创建指定数量的数组X
,可以像普通数组一样访问:Singleton&instance=Singleton[0].getInstance()代码>
请注意,我的示例代码使用了“新”C++11标准库中的功能。我不确定我是否正确理解了您的问题,但对我来说,单例的“集合”是不相关的。您有固定数量的单例,将它们称为Singleton1
到SingletonX
,其中X
在编译时已知。这对线程来说并不重要
对于实际的单例,您可以让它们从处理每线程部分的单个模板基类继承。大概是这样的:
template<class B>
struct SingletonBase
{
static B &getInstance()
{
// One instance per thread
static std::unordered_map<std::thread::id, B> intances;
if (instances.find(std::this_thread::get_id()) == instances.end())
instances[std::this_thread::get_id()] = B{};
return instances[std::this_thread::get_id()];
}
};
class Singleton1 : public SingletonBase<Singleton1>
{
// ...
};
这将在编译时创建一个指定数量的数组X
,然后