【问题标题】:Limiting Singleton instance to thread将单例实例限制为线程
【发布时间】:2009-08-09 02:42:20
【问题描述】:

什么是实现单例的好方法,该单例仅限于寻找其实例的线程?是否有线程 ID 或我可以用来执行此操作的东西?我正在使用 Carbon 线程 API,但稍后也必须在 Windows 和纯 POSIX 上实现它,所以任何技术都值得赞赏。

【问题讨论】:

  • 这听起来像是一个可能的设计缺陷。你能解释一下你使用这种机制的背景吗?
  • 我有一个图形引擎,它使用单例来访问它的一些核心功能,我需要能够实例化引擎的多个实例以在不同的窗口中运行,这些窗口都在单独的线程上运行。

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


【解决方案1】:

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

【讨论】:

【解决方案2】:

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

雅各布

【讨论】:

    【解决方案3】:

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

    如果您的线程系统没有,并且您的线程系统确实有唯一的线程标识符,那么哈希表(以线程 ID 为关键字)可能是您最好的选择。

    【讨论】:

      【解决方案4】:

      我们使用一个将线程 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 的平台。请注意,关键部分仅用于返回/创建引用,一旦您拥有引用,所有调用都在关键部分之外。

      【讨论】:

        【解决方案5】:

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

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

        虽然代码是用 Objective-C 编写的,但在其他语言中的想法应该是相同的,恕我直言。

        【讨论】:

          【解决方案6】:

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

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

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

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

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

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

          【讨论】:

            猜你喜欢
            • 2013-06-02
            • 2012-01-27
            • 2011-01-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多