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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: [решено] qrand() внутри потока  (Прочитано 12092 раз)
serg_hd
Хакер
*****
Offline Offline

Сообщений: 668



Просмотр профиля
« : Май 10, 2010, 14:36 »

Если ипользовать метод qrand() (или просто rand()) внутри потока, то он почему-то всё время возвращает одно и то же число:
Код
C++ (Qt)
run()
{
qDebug() << qrand();
}
 
Если за его пределами, то всё нормально, числа разные. В чём причина, может кто-нибудь в курсе?
Сами потоки запускаются в разное время.
« Последнее редактирование: Май 10, 2010, 14:47 от serg_hd » Записан

kubuntu/Win7/x64/NetBeans
serg_hd
Хакер
*****
Offline Offline

Сообщений: 668



Просмотр профиля
« Ответ #1 : Май 10, 2010, 14:48 »

Не совсем понял с чем связано (именно касательно потока), но помогло:
run()
{
 qsrand(QTime(0,0,0).msecsTo(QTime::currentTime()));
 int iRand = (int)qrand();
 qDebug() << iRand;
}
Записан

kubuntu/Win7/x64/NetBeans
Alex Custov
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2063


Просмотр профиля
« Ответ #2 : Май 10, 2010, 15:21 »

доку надо читать

Цитировать
The sequence of random numbers generated is deterministic per thread. For example, if two threads call qsrand(1) and subsequently calls qrand(), the threads will get the same random number sequence.

qsrand/qrand - thread safe функции, они работают per-thread, и хранят свои промежуточные значения в TLS.
Записан
garryHotDog
Гость
« Ответ #3 : Май 10, 2010, 15:41 »

сталкивался с такой проблемой, что в разных потоках были одинаковые случайные числа....твой код(функция run) имеет туже ошибку что была у меня:
Код
C++ (Qt)
[b]qsrand(QTime(0,0,0).msecsTo(QTime::currentTime()));[/b]
int iRand = (int)qrand();
qDebug() << iRand;
 

ты инициализируешь каждый раз рандомизатор с определенным значеним (кол-во секунд) - ОШИБКА: если 2 потока будут созданы в один и тот же интервал времени у них будут одни и те же случайные числа....
Решение
выполняй qsrand(QTime(0,0,0).msecsTo(QTime::currentTime())); в констукторе главного (основного) класса ТОЛЬКО 1 РАЗ (например в конструкторе), а в потоках (run()) используй просто qrand()....и все будет ок Смеющийся
Записан
serg_hd
Хакер
*****
Offline Offline

Сообщений: 668



Просмотр профиля
« Ответ #4 : Май 10, 2010, 15:45 »

... если 2 потока будут созданы в один и тот же интервал времени
дело в том, что не будут  Улыбающийся. Это контролирует другой класс.
Решение
выполняй qsrand(QTime(0,0,0).msecsTo(QTime::currentTime())); в констукторе главного (основного) класса ТОЛЬКО 1 РАЗ (например в конструкторе), а в потоках (run()) используй просто qrand()....и все будет ок Смеющийся
Спасибо, попробовал. Числа одинаковые.
главного (основного) класса
Имеется ввиду ведь класс-наследник QThread'a у которого этот метод run()? Если да, то особой роли этот факт (в конструкторе или нет) играть не будет, т.к. поток запускается сразу же после создания объекта этого класса. Да и числа, как выше написал, будут одинаковые.
« Последнее редактирование: Май 10, 2010, 15:56 от serg_hd » Записан

kubuntu/Win7/x64/NetBeans
SimpleSunny
Гость
« Ответ #5 : Май 10, 2010, 18:55 »

... если 2 потока будут созданы в один и тот же интервал времени
дело в том, что не будут  Улыбающийся. Это контролирует другой класс.

Мало ли что может случится потом, поэтому лучше немного обезопасить себя.

qsrand(QDateTime::currentDateTime().toTime_t() + int(this));

Записан
serg_hd
Хакер
*****
Offline Offline

Сообщений: 668



Просмотр профиля
« Ответ #6 : Май 10, 2010, 19:04 »

Мало ли что может случится потом, поэтому лучше немного обезопасить себя.

qsrand(QDateTime::currentDateTime().toTime_t() + int(this));
да, в ходе экспериментов это оказался наилучший вариант, блародарствую
Записан

kubuntu/Win7/x64/NetBeans
Alex Custov
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2063


Просмотр профиля
« Ответ #7 : Май 10, 2010, 19:13 »

QDateTime::currentDateTime().toTime_t()

блин, ну напишите вы ::time(0), зачем так сложно-то Улыбающийся
Записан
garryHotDog
Гость
« Ответ #8 : Май 10, 2010, 23:04 »

Цитировать
Цитата: garryHotDog от Сегодня в 03:41
главного (основного) класса
Имеется ввиду ведь класс-наследник QThread'a у которого этот метод run()? Если да, то особой роли этот факт (в конструкторе или нет) играть не будет, т.к. поток запускается сразу же после создания объекта этого класса. Да и числа, как выше написал, будут одинаковые.
я имел ввиду выполнить инициализацию qsrand() в каком то одном классе(не потоке), а qrand использовать уже в потоках без повторного использования qsrand()!!!!
Записан
serg_hd
Хакер
*****
Offline Offline

Сообщений: 668



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

Цитировать
Цитата: garryHotDog от Сегодня в 03:41
главного (основного) класса
Имеется ввиду ведь класс-наследник QThread'a у которого этот метод run()? Если да, то особой роли этот факт (в конструкторе или нет) играть не будет, т.к. поток запускается сразу же после создания объекта этого класса. Да и числа, как выше написал, будут одинаковые.
я имел ввиду выполнить инициализацию qsrand() в каком то одном классе(не потоке), а qrand использовать уже в потоках без повторного использования qsrand()!!!!
и так пробовал, числа одинаковые
Записан

kubuntu/Win7/x64/NetBeans
Alex Custov
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2063


Просмотр профиля
« Ответ #10 : Май 11, 2010, 03:26 »

я имел ввиду выполнить инициализацию qsrand() в каком то одном классе(не потоке), а qrand использовать уже в потоках без повторного использования qsrand()!!!!

qsrand() надо делать для каждого потока, желательно разными значениями. Выше уже всё написано, а в документации и подавно.
Записан
garryHotDog
Гость
« Ответ #11 : Май 11, 2010, 16:12 »

Цитировать
qsrand() надо делать для каждого потока, желательно разными значениями. Выше уже всё написано, а в документации и подавно.

я так сначала и пробовал: в каждом потоке делал qsrand(), в качестве параметра передавал время в мс....но получалось так что несколько потоков создавалось в один временной интервал и "случайные" числа после qrand() оказывались одинаковыми...попробуй сам!
Записан
Alex Custov
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2063


Просмотр профиля
« Ответ #12 : Май 11, 2010, 16:59 »

Цитировать
qsrand() надо делать для каждого потока, желательно разными значениями. Выше уже всё написано, а в документации и подавно.

я так сначала и пробовал: в каждом потоке делал qsrand(), в качестве параметра передавал время в мс....но получалось так что несколько потоков создавалось в один временной интервал и "случайные" числа после qrand() оказывались одинаковыми...попробуй сам!

Я это знаю, по-другому и быть не может - псеводослучайные числа считаются по формуле. Делать qsrand() один раз вне потоков - НЕ правильно, почему - уже написано несколько раз. Чтобы избежать одинаковых рядов можно к зерну добавлять какое-то случайное число, как уже показали - например int(this), или значение неинициализированной переменной (я об этом и написал в предыдущем сообщении).
« Последнее редактирование: Май 11, 2010, 17:03 от Alex Custov » Записан
garryHotDog
Гость
« Ответ #13 : Май 11, 2010, 17:02 »

хмм...что то я все равно не понял почему один раз нельзя!? можно еще раз?
Записан
Alex Custov
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2063


Просмотр профиля
« Ответ #14 : Май 11, 2010, 17:05 »

хмм...что то я все равно не понял почему один раз нельзя!? можно еще раз?

qrand() и qsrand() работают с одним конкретным, текущим, TLS, сколько раз ещё написать?! Строит глазки Именно поэтому они потокобезопасны.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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