Singleton getInstance in workflow methods

This question is about the use of single object getter methods in worker threads. Here are some pseudo-codes:

// Singleton class which contains data
class MyData
{
    static MyData* sMyData ;

    int  mData1[1024];
    int  mData2[1024];
    int  mData3[1024];

    MyData* getInstance()
    {
        // sMyData is created in the very beginning.
        return sMyData ;
    }

    void getValues(int idx, int& data1,int& data2,int& data3)
    {
        data1 = mData1[idx];
        data2 = mData2[idx];
        data3 = mData3[idx];
    }

    int* getData1()
    {
        return &mData1[0];
    }
}

class MyThread
{
    void workerMethod()
    {
        MyData* md = MyData::getInstance();

        int d1,d2,d3;
        md->getValue( 12, d1,d2,d3 );

        int* data1 = md->getData1();
        d1 = data1[34];
    }
}

      

Now, as you can see, I have some getter methods (read-only), MyData :: getInstance (), MyData :: getValue () and MyData :: getData1 (). The first question is, how thread safe are these methods?

Since they are often called methods, securing these methods with a mutex is what I'm trying to avoid.

Second question: what is the suggested way to read data from central sources in a multithreaded application, especially in working methods.

Thank!

Floor

+1


source to share


5 answers


Provided that no other thread tries to write data to your singleton object, you don't need to protect it: by definition, multiple readers in the absence of a writer are thread safe. This is a generic pattern where program initialization code sets up a single item, which is then read only by worker threads.



However, if any thread ever writes this data and others read from it, you must protect it in some way. If you have a lot of readers and only a casual writer, it's worth considering some kind of read-write lock that allows multiple readers in the absence of any writers.

+5


source


There is no way to determine if this might be thread safe. If the data is initialized when the object is created and never changes, this will work correctly. If you mutate the underlying data using other methods, the readers will have to do some kind of sync with the writers, there is no way around this.



Depending on what you are doing, you can use something lighter than a mutex, like atomic updates, synchronize commands, or use read / write locks, but without knowing more about what you are doing, it is impossible to tell.

+2


source


Your methods are fine, but you have two main problems.

First, MyData :: getInstance () must be static and not instantiated. To minimize the use of mutexes, you should check the double checked lock .

Second, thread safety depends on the callers of the getter methods, not on the MyData class. If that's what you're looking for, then great. If not, then you have to come up with some sort of access control in MyClass. Also, since your datatype is just a base type (int), chances are you will never see any synchronization problems until your code is built.

+1


source


First go back and read this question to get a better version of singelton:
Can anyone provide me with a sample Singleton in C ++?

Also note: Do NOT use singleton as glorified global variable.
It just adds complexity to poor design. Just use a global variable.

As long as you are only reading the singleton, it is thread safe when used.

The only point that is not thread safe (not guaranteed by the language) is at creation time. So technically you should add locks around the part that instantiates to ensure that the singleton is fully instantiated before anyone can use it.

Note. Don't be fooled by using double locking to optimize your locking strategy. This can be done NOT to work correctly in C ++. Read this DDJ article .

If you can guarantee that the singleton will be created (perhaps the first call is too getInstance ()) within the same threading environment (before any threads are created), then you can eliminate the need for locks during instantiation.

If you change your code so that other threads can write in the singleton, you need to think about blocking and consistency. You need a lock if your records are not atomic. If your record simply updates one integer, then it is no longer required atomic. If your code is not atomic:

  • Writing multiple integers inside a method
  • Reading and then writing

Then you will need to lock the object until all writes are complete and therefore will also have locks on methods that have read access to stop reading them from the object, while another method updates the object.

Hence, this is another reason why member members should only be accessed using member methods.

+1


source


For thread safety, you need to look at the class as a whole. As written, your class will not be thread safe. While the getValues ​​method is fine, the getData1 method has problems.

You say these are (read-only) getter methods. However, none of them are declared as const methods. GetData1 is not valid as a const method because it returns a non const pointer. Also, returning a pointer to private class data is bad since you are exposing your implementation.

If it's a singleton class to store some essentially static set of data on initialization before you start executing threads, all of your accessors should be const methods. GetInstance must also return a const pointer to the class (and be a static method as mentioned in another answer).

0


source







All Articles