简体   繁体   English

将Singleton实例限制为线程

[英]Limiting Singleton instance to thread

What is a good way to implement a singleton that will be restricted only to the thread that seeks its instance? 什么是实现仅限制于寻求其实例的线程的单例的好方法? Is there a thread id or something that I can use to do that? 是否有线程ID或我可以用来做的事情? I'm using Carbon threading API but will have to implement this on windows and pure POSIX later too, so any technique is appreciated. 我正在使用Carbon线程API,但稍后也将不得不在Windows和纯POSIX上实现此功能,因此欢迎您使用任何技术。

How about something similar to ThreadLocal in Java? 类似于Java中的ThreadLocal的东西如何? Posix/Carbon should have something ThreadLocal right? Posix / Carbon应该具有ThreadLocal的功能吗?

In the past, I have leveraged a hashmap or index to store data structures that are per-thread inside of a single global thread-safe data structure. 过去,我利用哈希图或索引来存储单个全局线程安全数据结构中每个线程的数据结构。 For instance, if you provide the id for each thread as an incrementing integer, you can store your data structure in a pre-allocated array at the index of the thread it. 例如,如果您提供每个线程的id作为递增整数,则可以将数据结构存储在线程的索引处的预分配数组中。 If you are leveraging thread IDs that are provided by the operating system or need to be more flexible, then a thread safe HashMap or HashTable will come in quite handy. 如果您利用操作系统提供的线程ID或需要更加灵活,那么线程安全的HashMap或HashTable将非常有用。

Jacob 雅各布

I'd want to put the singleton pointer into whatever the system's thread local storage method is. 我想将单例指针放到系统的线程本地存储方法中。 You've named several, and I don't know the right incantations for them, but most threading systems have some kind of thread local storage concept. 您已经命名了几个,但我不知道它们的正确含义,但是大多数线程系统都有某种线程本地存储概念。

If your threading system does not, AND your threading system does have a unique thread identifier, then a hash table (keyed by thread id) is probably your best bet. 如果您的线程系统没有,并且您的线程系统确实具有唯一的线程标识符,那么哈希表(由线程ID键入)可能是最好的选择。

We use a class that stores a map of thread id to data to implement our thread local storage. 我们使用一个存储线程ID到数据的映射的类来实现我们的线程本地存储。 This seems to work very well, then an instance of this class can be placed anywhere you require thread local storage. 这似乎工作得很好,然后可以将此类的实例放置在需要线程本地存储的任何位置。 Normally clients use an instance of as a static private field. 通常,客户端使用的实例作为静态私有字段。

Here is a rough outline of the code 这是代码的粗略概述

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;
};

This is then used as 然后用作

class A {
    // ...

    void doStuff();
private:
   static ThreadLocal<Foo> threadLocalFoo;
};

ThreadLocal<Foo> A::threadLocalFoo;

void A::doStuff() {
    // ...
    threadLocalFoo.value().bar();
    // ...
}

This is simple and works on any platform where you can get the thread id. 这很简单,并且可以在任何可以获取线程ID的平台上使用。 Note the Critical Section is only used to return/create the reference, once you have the reference all calls are outside the critical section. 请注意,关键部分仅用于返回/创建引用,一旦有了引用,所有调用都将在关键部分之外。

I'm not sure whether this will answer your question, but in my Design Pattern class, I've learned something like this: 我不确定这是否会回答您的问题,但是在我的设计模式课程中,我学到了以下内容:

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

Although the code is in Objective-C, the idea should be about the same in other language, IMHO. 尽管代码是使用Objective-C编写的,但该想法应该与其他语言恕我直言差不多。

If you're happy with pthreads, you should be looking at 如果您对pthreads感到满意,则应该关注

This should cover OSX and linux (I haven't used Carbon, but I'm guessing that it uses real OS threads and therefore plays nicely with pthreads). 这应该涵盖OSX和linux(我没有使用Carbon,但是我猜测它使用了真正的OS线程,因此可以很好地与pthread一起使用)。

Windows has the same basic idea with different names and a slightly different interface: Windows具有相同的基本概念,但名称不同且界面略有不同:

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

This allows you to access the "singleton"(*) for a thread only from that thread, but it sounds like that's what you want. 这使您只能从该线程访问线程的“单身”(*),但这听起来就是您想要的。 If you want to be able to access any thread's object from any other thread, then you need a structure keyed on a pthread_t , and almost certainly some synchronisation. 如果您希望能够从任何其他线程访问任何线程的对象,则需要在pthread_t上键入键的结构,并且几乎可以肯定需要进行一些同步。 You get pthread_t values (that is, thread IDs) from pthread_self or pthread_create . 您可以从pthread_selfpthread_create获得pthread_t值(即线程ID)。

(*) If you have one per thread, it's technically not a singleton... (*)如果每个线程只有一个,那么从技术上讲不是单例...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM