Need advice to make code multithreaded

I got code that is not intended for a multi-threaded application, now I need to change the code to support multi-threading.

I have a Singleton ( MyCenterSigltonClass) class , which is based on an instruction in: http://en.wikipedia.org/wiki/Singleton_pattern I made it thread safe

Now I see inside a class that contains 10-12 members, some with getter / setter methods. Some members are declared static and have a pointer to a class, for example:

static Class_A*    f_static_member_a;
static Class_B*    f_static_member_b;

I defined a mutex for these members (e.g. mutex_a). Inside the class ( Class_A), I did not add the mutex directly to mine MyCenterSigltonClass, the reason is that they are one-to-one my MyCenterSigltonClass, I think I have an option to define mutex in the class ( MyCenterSigltonClass) or ( Class_A) for f_static_member_a.

1) Am I right?

In addition, my Singleton ( MyCenterSigltonClass) class contains some other elements, such as

Class_C  f_classC;

for such member variables, do I have to define a mutex for each of them in MyCenterSigltonClassto make them thread safe? what would be a good way to handle these cases?

Appreciate any suggestion.

-Nima

+3
source share
4 answers

, . -, , .

, /. , . , , , . .

class A
{
private:
    int mValuesCount;
    int* mValues;

public:
    A(int count, int* values)
    {
        mValuesCount = count;
        mValues = (count > 0) ? new int[count] : NULL;
        if (mValues)
        {
            memcpy(mValues, values, count * sizeof(int));
        }
    }

    int getValues(int count, int* values) const
    {
        if (mValues && values)
        {
            memcpy(values, mValues, (count < mValuesCount) ? count : mValuesCount);
        }
        return mValuesCount; 
    }
};

class B
{
private:
    A* mA;

public:
    B()
    {
        int values[5] = { 1, 2, 3, 4, 5 };
        mA = new A(5, values);
    }
    const A* getA() const { return mA; }
};

, . , . , A:

class A
{
private:
    int mValuesCount;
    int* mValues;

public:
    A(int count, int* values)
    {
        mValuesCount = 0;
        mValues = NULL;
        setValues(count, values);
    }

    int getValues(int count, int* values) const
    {
        if (mValues && values)
        {
            memcpy(values, mValues, (count < mValuesCount) ? count : mValuesCount);
        }
        return mValuesCount; 
    }

    void setValues(int count, int* values)
    {
        delete [] mValues;

        mValuesCount = count;
        mValues = (count > 0) ? new int[count] : NULL;
        if (mValues)
        {
            memcpy(mValues, values, count * sizeof(int));
        }
    }
};

, B:: getA(), , . :

Thread A: a->getValues(maxCount, values);
Thread B: a->setValues(newCount, newValues);

, Thread B mValues, Thread A . A mValues ​​ mValuesCount:

    int getValues(int count, int* values) const
    {
        // TODO: Lock mutex.
        if (mValues && values)
        {
            memcpy(values, mValues, (count < mValuesCount) ? count : mValuesCount);
        }
        int returnCount = mValuesCount;
        // TODO: Unlock mutex.
        return returnCount; 
    }

    void setValues(int count, int* values)
    {
        // TODO: Lock mutex.
        delete [] mValues;

        mValuesCount = count;
        mValues = (count > 0) ? new int[count] : NULL;
        if (mValues)
        {
            memcpy(mValues, values, count * sizeof(int));
        }
        // TODO: Unlock mutex.
    }

/ mValues ​​ mValuesCount. , , getValues ​​(), .

, , A :

class A
{
private:
    int mValuesCount;
    int* mValues;

public:
    A(int count, int* values)
    {
        mValuesCount = 0;
        mValues = NULL;
        setValues(count, values);
    }

    int getValueCount() const { return mValuesCount; }

    int getValues(int count, int* values) const
    {
        if (mValues && values)
        {
            memcpy(values, mValues, (count < mValuesCount) ? count : mValuesCount);
        }
        return mValuesCount; 
    }

    void setValues(int count, int* values)
    {
        delete [] mValues;

        mValuesCount = count;
        mValues = (count > 0) ? new int[count] : NULL;
        if (mValues)
        {
            memcpy(mValues, values, count * sizeof(int));
        }
    }
};

:

Thread A: int maxCount = a->getValueCount();
Thread A: // allocate memory for "maxCount" int values
Thread B: a->setValues(newCount, newValues);
Thread A: a->getValues(maxCount, values);

A , getValueCount() getValues ​​() , Thread B Thread A. , , , . A , , A, / :

Thread A: a->lockValues();
Thread A: int maxCount = a->getValueCount();
Thread A: // allocate memory for "maxCount" int values
Thread B: a->setValues(newCount, newValues); // Blocks until Thread A calls unlockValues()
Thread A: a->getValues(maxCount, values);
Thread A: a->unlockValues();
Thread B: // Completes call to setValues()

, , , , , .

, , , . , , .

, singleton , . :

  • - singleton , ( , )?
  • - ?
  • , - , ?
  • , ?

, ( ). , , / ( ). , ( ). , (, Foo Bar, Bar Foo).

. , . , , ( , ).

+1

, , , . , , , .

, singleton , .

0

. , , :

class foo
{
public:
  ...
  void some_op()
  {
    // acquire "lock_" and release using RAII ...
    Lock(lock_);
    a++;
  }

  void set_b(bar * b)
  {
    // acquire "lock_" and release using RAII ...
    Lock(lock_);
    b_ = b;
  }

private:

  int a_;
  bar * b_;

  mutex lock_;
}

, " " . . , . , , .. concurrency, .

, , TSS, . , "func" :

class Foo;
void func (Foo & f)
{
  f.some_op();  // Foo::some_op() of course needs to be thread-safe.
}

// Thread 1
Foo a;
func(&a);

// Thread 2
Foo b;
func(&b);

func , , , . , , . .

. , , , Boost.Thread, , API- .

0

I would recommend Interlocked .... Methods to increase, decrease and compare AndSwap values ​​when using code that should be multi-threaded. I have no experience with C ++, but a quick search http://www.bing.com/search?q=c%2B%2B+interlocked shows a lot of supporting tips. If you need perfection, they will most likely be faster than blocking.

0
source

Source: https://habr.com/ru/post/1733443/


All Articles