将Singleton实例限制为线程

时间:2009-08-09 02:42:21

标签: c++ winapi singleton posix macos-carbon

实现一个仅限于寻求其实例的线程的单例的好方法是什么?是否有线程ID或我可以用来做的事情?我正在使用Carbon线程API但是必须稍后在Windows和纯POSIX上实现它,所以任何技术都值得赞赏。

6 个答案:

答案 0 :(得分:2)

与Java中的ThreadLocal类似的东西怎么样? Posix / Carbon应该有一些ThreadLocal吗?

答案 1 :(得分:1)

过去,我利用散列图或索引来存储单个全局线程安全数据结构中每个线程的数据结构。例如,如果您将每个线程的id提供为递增整数,则可以将数据结构存储在线程索引处的预分配数组中。如果您正在利用操作系统提供的线程ID或需要更灵活,那么线程安全的HashMap或HashTable将会非常方便。

雅各

答案 2 :(得分:1)

我想将单例指针放入系统的线程本地存储方法中。你已经命名了几个,我不知道它们的正确咒语,但大多数线程系统都有某种线程本地存储概念。

如果您的线程系统没有,并且您的线程系统确实有唯一的线程标识符,则哈希表(由线程ID键入)可能是您最好的选择。

答案 3 :(得分:1)

我们使用一个类来存储线程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的平台上运行。注意,关键部分仅用于返回/创建引用,一旦引用,所有调用都在临界区之外。

答案 4 :(得分:0)

我不确定这是否会回答你的问题,但在我的设计模式课程中,我学到了这样的东西:

- (id) getInstance{
     @synchronized(self){
          if (mySingletonInstance == nil){
               @synchronized(self){
                   mySingletonInstance = [[mySingleton alloc] init];
               }
          }
     }
     return mySingletonInstance;
}

虽然代码是在Objective-C中,但这个想法在其他语言中应该是一样的,恕我直言。

答案 5 :(得分:0)

如果你对pthreads感到满意,你应该看看

这应该涵盖OSX和linux(我没有使用过Carbon,但我猜它使用真正的操作系统线程,因此可以很好地使用pthreads。)

Windows具有相同的基本思想,名称不同,界面略有不同:

http://msdn.microsoft.com/en-us/library/ms686991.aspx

这允许您仅从该线程访问线程的“单例”(*),但听起来就像您想要的那样。如果您希望能够从任何其他线程访问任何线程的对象,那么您需要一个键入pthread_t的结构,几乎肯定会有一些同步。您从pthread_tpthread_self获得pthread_create个值(即线程ID)。

(*)如果每个线程有一个,那么从技术上讲它不是单身......