Как и какие данные должны синхронизироваться в многопоточном C ++

Я создаю небольшое приложение, которое имеет поток рендеринга и несколько рабочих потоков для задач, которые могут быть выполнены рядом с рендерингом, например загрузка файлов на какой-то сервер. Теперь в этих рабочих потоках я использую разные объекты для хранения информации обратной связи и делюсь ею с потоком рендеринга, чтобы прочитать их для целей вывода. Итак, render = output, worker = input. Эти общие объекты - это int, float, bool, строка STL и список STL.

У меня это работало несколько месяцев, и все было в порядке, кроме двух случайных сбоев во время вывода, но теперь я узнал о синхронизации потоков. Я читаю int, bool и т. Д., Не требуют синхронизации, и я думаю, что это имеет смысл, но когда я смотрю на строку и список, я боюсь возможных сбоев, если 2 потока попытаются прочитать / записать объект одновременно. В основном я ожидаю, что один поток изменяет размер строки, в то время как другой может использовать устаревший размер для циклического перебора своих символов, а затем чтения из нераспределенной памяти. Сегодня вечером я хочу создать небольшой тестовый сценарий с двумя потоками, которые пишут / читают один и тот же объект в цикле, однако я также надеялся получить здесь некоторые идеи.

Я читал о CriticalSection в Win32 и подумал, что стоит попробовать. Тем не менее, я не уверен, как лучше всего это реализовать. Если я помещаю его в начало и в конец чтения / функции, мне кажется, что какое-то время было потрачено впустую. И если я заключу EnterCriticalSection и LeaveCriticalSection в функции Set и Get для каждого объекта, который я хочу синхронизировать между потоками, это будет большой административной необходимостью.

Думаю, мне нужно пролезть через больше ссылок.


Хорошо, я все еще не знаю, что делать дальше. Я изучал ссылки, предоставленные StackedCrooked, но до сих пор не знаю, как это сделать.

Я собрал это скопированное / измененное вместе сейчас и понятия не имею, как продолжить или что делать: у кого-то есть идеи?

class CSync
{
public:
    CSync()
    : m_isEnter(false)
    { InitializeCriticalSection(&m_CriticalSection); }
    ~CSync()
    { DeleteCriticalSection(&m_CriticalSection); }
    bool TryEnter()
    {
        m_isEnter = TryEnterCriticalSection(&m_CriticalSection)==0 ? false:true;
        return m_isEnter;
    }
    void Enter()
    {
        if(!m_isEnter)
        {
            EnterCriticalSection(&m_CriticalSection);
            m_isEnter=true;
        }
    }
    void Leave()
    {
        if(m_isEnter)
        {
            LeaveCriticalSection(&m_CriticalSection);
            m_isEnter=false;
        }
    }

private:
    CRITICAL_SECTION m_CriticalSection;
    bool m_isEnter;
};

/* not needed

class CLockGuard
{
public:
    CLockGuard(CSync& refSync) : m_refSync(refSync) { Lock(); }
    ~CLockGuard() { Unlock(); }

private:
    CSync& m_refSync;

    CLockGuard(const CLockGuard &refcSource);
    CLockGuard& operator=(const CLockGuard& refcSource);
    void Lock() { m_refSync.Enter(); }
    void Unlock() { m_refSync.Leave(); }
};*/

template<class T> class Wrap
{
public:
    Wrap(T* pp, const CSync& sync)
        : p(pp)
        , m_refSync(refSync)
    {}
    Call_proxy<T> operator->() { m_refSync.Enter(); return Call_proxy<T>(p); }
private:
    T* p;
    CSync& m_refSync;
};

template<class T> class Call_proxy
{
public:
    Call_proxy(T* pp, const CSync& sync)
        : p(pp)
        , m_refSync(refSync)
    {}
    ~Call_proxy() { m_refSync.Leave(); }
    T* operator->() { return p; }
private:
    T* p;
    CSync& m_refSync;
};


int main
{
    CSync sync;
    Wrap<string> safeVar(new string);
    // safeVar what now?
    return 0;
};

Хорошо, я готовил небольшой тест сейчас, чтобы увидеть, дают ли мои попытки что-то хорошее, так что сначала Я создал настройку, чтобы приложение вылетало, я полагал ...

Но это не приводит к сбою !? Значит ли это, что теперь мне не нужна синхронизация? Что нужно программе для эффективного сбоя? А если не вылетает, зачем вообще заморачиваться. Кажется, я снова упускаю какой-то момент. Есть идеи?

string gl_str, str_test;

void thread1()
{
    while(true)
    {
        gl_str = "12345";
        str_test = gl_str;
    }
};

void thread2()
{
    while(true)
    {
        gl_str = "123456789";
        str_test = gl_str;
    }
};

CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)thread1, NULL, 0, NULL );
CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)thread2, NULL, 0, NULL );

Просто добавил еще кое-что, и теперь он вылетает при вызове clear (). Хороший.

void thread1()
{
    while(true)
    {
        gl_str = "12345";
        str_test = gl_str;
        gl_str.clear();
        gl_int = 124;
    }
};

void thread2()
{
    while(true)
    {
        gl_str = "123456789";
        str_test = gl_str;
        gl_str.clear();
        if(gl_str.empty())
            gl_str = "aaaaaaaaaaaaa";
        gl_int = 244;
        if(gl_int==124)
            gl_str.clear();
    }
};
0
задан xezon 15 December 2011 в 19:07
поделиться