将 Singleton 实例限制为线程
-
12-09-2019 - |
题
实现仅限于寻找其实例的线程的单例的好方法是什么?是否有一个线程 id 或者我可以用来做到这一点的东西?我正在使用 Carbon 线程 API,但稍后也必须在 Windows 和纯 POSIX 上实现这一点,因此任何技术都值得赞赏。
解决方案
在过去,我已经利用一个HashMap或索引是每线程的单个全局线程安全数据结构的内部存储的数据结构。举例来说,如果您提供的每个线程的ID作为递增的整数,你可以线程它的索引存储在预先分配的数组数据结构。如果你正在利用操作系统提供或需要更灵活的是线程ID,然后一个线程安全的HashMap的哈希表或会在相当方便。
雅各
其他提示
如何类似ThreadLocal的Java中的东西吗? POSIX /炭应该有一些ThreadLocal的吧?
我愿意把单指针到任何系统的线程本地存储方法。你叫几个,我不知道正确的咒语他们,但大多数线程系统有某种线程本地存储的概念。
如果您的线程系统不和你的线程系统确实有一个唯一的线程标识符,那么一个哈希表(由线程ID键控)可能是你最好的选择。
我们使用存储映射一个主题ID数据来实现我们的线程本地存储类。这似乎很好地工作,那么这个类的一个实例,可以放在任何地方,你需要线程本地存储。通常客户端使用的一个实例为静态私有字段。
下面是代码的一个粗略轮廓
template <class T>
struct ThreadLocal {
T & value()
{
LockGuard<CriticalSection> lock(m_cs);
std::map<int, T>::iterator itr = m_threadMap.find(Thread::getThreadID());
if(itr != m_threadMap.end())
return itr->second;
return m_threadMap.insert(
std::map<int, T>::value_type(BWThread::getThreadID(), T()))
.first->second;
}
CriticalSection m_cs;
std::map<int, T> m_threadMap;
};
这随后被用作
class A {
// ...
void doStuff();
private:
static ThreadLocal<Foo> threadLocalFoo;
};
ThreadLocal<Foo> A::threadLocalFoo;
void A::doStuff() {
// ...
threadLocalFoo.value().bar();
// ...
}
这是简单,适用于任何平台,在这里你可以得到线程ID上。注意临界区只用于返回/创建引用,一旦你有参考的所有呼叫都临界区外。
我不知道这是否会回答你的问题,但在我的设计模式类,我已经学会了这样的事情:
- (id) getInstance{
@synchronized(self){
if (mySingletonInstance == nil){
@synchronized(self){
mySingletonInstance = [[mySingleton alloc] init];
}
}
}
return mySingletonInstance;
}
虽然代码是在Objective-C,这个想法应约在其他语言相同,IMHO。
如果您对 pthreads 感到满意,您应该看看
pthread_key_create
pthread_setspecific
pthread_getspecific
这应该涵盖 OSX 和 Linux(我没有使用 Carbon,但我猜测它使用真正的操作系统线程,因此可以很好地与 pthreads 配合)。
Windows 具有相同的基本思想,但名称不同,界面也略有不同:
http://msdn.microsoft.com/en-us/library/ms686991.aspx
这允许您仅从该线程访问该线程的“单例”(*),但听起来这就是您想要的。如果您希望能够从任何其他线程访问任何线程的对象,那么您需要一个以 pthread_t
, ,几乎肯定还有一些同步。你得到 pthread_t
值(即线程 ID)来自 pthread_self
或者 pthread_create
.
(*) 如果每个线程都有一个,那么从技术上讲它不是单例......