Russian Qt Forum
Ноябрь 23, 2024, 04:01 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2] 3   Вниз
  Печать  
Автор Тема: [РЕШЕНО] Потоки и модель данных, или немного эзотерики.  (Прочитано 19020 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #15 : Май 27, 2013, 11:24 »

Хотя если речь о том, что 4-х байтный double может слететь на 16-битной оси - это нормально.
Вопрос стоял в том, почему программа не вылетает, оказалось что в атомарности процесса присваивания используемой структуры.
8-байтный double (или long long) может успешно слететь на 64-битной оси Улыбающийся Но суть не в том "атомарно или нет", ошибка (отсутствие нужной блокировки) в большинстве случаев не ведет к вылету (это еще хорошо), а просто тихо гадит, напр
Код
C++ (Qt)
++count;  // при отсутствии лока значение count может быть неверным с 2 или более нитками
 

Записан
ctin
Гость
« Ответ #16 : Май 27, 2013, 13:42 »

Ой, да. 8-ми байтный Улыбающийся))
Спасибо, не знал что гадит.
 А что такое нитками?

 thechicho
атомарные переменные и члены структур лочить не надо. Можете написать тестовую программку и посмотреть.
« Последнее редактирование: Май 28, 2013, 21:34 от ctin » Записан
thechicho
Гость
« Ответ #17 : Май 27, 2013, 14:29 »

//атомарные переменные и члены структур лочить не надо
чо?
Записан
ctin
Гость
« Ответ #18 : Май 27, 2013, 16:06 »

Если процессор за один такт заменит значение, то считай оно уже залочено. Луркай "volatile" и "атомарный". Членов классов и структур это тоже касается.
Записан
thechicho
Гость
« Ответ #19 : Май 27, 2013, 16:19 »

//Если процессор за один такт заменит значение, то считай оно уже залочено.

Код:
connect(this, SIGNAL(stopThread()), thread, SLOT(stopThread()));

void Thread::stopThread()
{
    mutex.lock();
    STOP = true;
    mutex.unlock();
}

из главного потока посылается сигнал на остановку потоков. то есть не надо лочить STOP?
значение переменной хранится в памяти и мьютекс нужен, чтобы избежать одновременного доступа к одному участку памяти. причем тут процессор?
Записан
ctin
Гость
« Ответ #20 : Май 27, 2013, 17:19 »

STOP = true выполняется за один такт процессора, и если ты создаешь пару потоков с одной и той же функцией
Код:
void func()
{
    globalStruct->STOP = !globalStruct->STOP
}

вылета не будет.
Записан
thechicho
Гость
« Ответ #21 : Май 27, 2013, 17:23 »

а кто говорил, про вылет?

Цитировать
Но суть не в том "атомарно или нет", ошибка (отсутствие нужной блокировки) в большинстве случаев не ведет к вылету (это еще хорошо), а просто тихо гадит, напр

ты походу сам не понимаешь о чем говоришь
Записан
ctin
Гость
« Ответ #22 : Май 27, 2013, 23:22 »

Пиздец какой-то.
Записан
Serr500
Гость
« Ответ #23 : Май 28, 2013, 08:12 »

STOP = true выполняется за один такт процессора
Шо, всегда?  Подмигивающий Смеющийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #24 : Май 28, 2013, 10:24 »

По поводу "тактов" - присваивание может обращаться к памяти, и тогда неизвестно сколько тактов понадобится процессору. Другое довольно популярное заблуждение что, якобы, "атомарно все что делается одной машинной командой". Напр в одной статье видел примерно такое
Код:
inc [offset]
Инкремент одна команла - стало быть, "атоиарно". Однако если открыть исходники атомарного инкремента int (хоть в Qt), мы почему-то нигде не увидим просто "inc", а lock и CAS по полной.

"Если атомарно - можно обойтись без лока" - это часто оказывается ошибкой, напр
Код
C++ (Qt)
if (a > b)
 a = b;
 
Все атомарно, но др нитка може вклиниться между 2-мя атомарными командами. Испуганный человек начинает страховаться и сует мутексы на каждом шагу. В результате 4 ядоа оказываются куда медленнее одного  Улыбающийся
Записан
ctin
Гость
« Ответ #25 : Май 28, 2013, 11:34 »

я сделаю приложение, где четыре потока без задержек будут ставить в одну переменную double либо 0, либо 10, и если перед этим будет не 0 или не 10 - выводить наружу значение через qDebug.
Записан
thechicho
Гость
« Ответ #26 : Май 28, 2013, 12:09 »

//Испуганный человек начинает страховаться и сует мутексы на каждом шагу. В результате 4 ядоа оказываются куда медленнее одного
ога медленнее на пару микросекунд Улыбающийся
в моем случае у меня 100500 проверок STOP. так что можно и без мьютекса написать, ничего от этого не изменится. но какбэ теория намекает, что нужно защищать переменную от одновременного доступа блокировкой. эта блокировка сработает единожды и произойдет выход из потоков и их уничтожение. то есть  остановка. о какой скорости может идти речь. да и вообще в контексте мьютекса можете пример привести, где он может повлиять значительно на скорость выполнения? требуются же микросекунды на лок, анлок
« Последнее редактирование: Май 28, 2013, 12:15 от thechicho » Записан
thechicho
Гость
« Ответ #27 : Май 28, 2013, 12:13 »

//я сделаю приложение, где четыре потока без задержек будут ставить в одну переменную double либо 0, либо 10, и если перед этим будет не 0 или не 10 - выводить наружу значение через qDebug.

и какой в этом смысл?

http://www.youtube.com/watch?v=JaGqGhRW5Ks
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #28 : Май 28, 2013, 13:06 »

я сделаю приложение, где четыре потока без задержек будут ставить в одну переменную double либо 0, либо 10, и если перед этим будет не 0 или не 10 - выводить наружу значение через qDebug.
Цитировать
Тестирование может показать наличие ошибок но не их отсутствие
Улыбающийся Попробуйте так
Код
C++ (Qt)
#pragma pack(push, 1)
struct CTest {
char ch;
double d;  // меняйте этот double
};
#pragma pack(pop)
 
А можно действовать проще - пройдите в отладчике по шагам
Код
C++ (Qt)
std::atomic <double> test(0);
test = 10;
 
Правда, насколько я знаю, эта радость доступна начиная с С++ 11. Внутри присваивания Вы увидите что все далеко не так просто
Записан
ctin
Гость
« Ответ #29 : Май 28, 2013, 21:31 »

Есть случаи тривиальные, типа
if(a > b)
   b = a;

Мы говорили о присваивании и ошибках.

Вот код
Код:
while(qApp && m_running)
    {
        double val = m_pModel->m_value;
        if(val != 0 && val != 11)
            qWarning() << "Оп-па!" << val;
        m_pModel->m_value = val ? 0 : 11;
    }
который проработал час в трех потоках, загрузив на 75% мой проц (угадай сколько ядер) и не вывесив ни одного сообщения. Пробную версию я делал, сообщения выводила.

Справедливости ради замечу, что код
Код:
        if(m_pModel->m_value != 0 && m_pModel->m_value != 11)
            qWarning() << "Оп-па!" << m_pModel->m_value;
        m_pModel->m_value = m_pModel->m_value ? 0 : 11;
выводит тонны сообщений типа
Цитировать
Ii-ia! 0
Ii-ia! 0
Ii-ia! 0
Ii-ia! 0
Ii-ia! 0
Ii-ia! 11

где m_value имеет тип double
Записан
Страниц: 1 [2] 3   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.216 секунд. Запросов: 23.