Я перенес код в класс java.util.Random в objectivec. Я хочу иметь идентичный генератор случайных чисел, чтобы он синхронизировался с серверным приложением, работающим на java. Теперь это безопасный перенос, и если нет, есть ли способ имитировать AtomicLong, как он находится в java? Пожалуйста, посмотрите мой код ниже.
static long long multiplier = 0x5DEECE66DL;
static long addend = 0xBL;
static long long mask = (0x1000000000000001L << 48) - 1;
-(void) initWithSeed:(long long) seed1 {
[self setRandomSeed: 0L];// = new AtomicLong(0L);
[self setSeed: seed1];
}
-(int) next:(int)bits {
long long oldseed, nextseed;
long long seed1 = [self.randomSeed longLongValue]; //AtomicLong
//do {
oldseed = seed1;
nextseed = (oldseed * multiplier + addend) & mask;
//} while (!seed.compareAndSet(oldseed, nextseed));
[self setRandomSeed: [NSNumber numberWithLongLong:nextseed]];
///int ret = (int)(nextseed >>> (48 - bits));
int ret = (unsigned int)(nextseed >> (48 - bits));
return ret;
}
-(void) setSeed:(long long) seed1 {
seed1 = (seed1 ^ multiplier) & mask;
[self setRandomSeed: [NSNumber numberWithLongLong:seed1]];
}
2 ответа
Если ваша цель - сделать генерацию этих чисел потокобезопасной, ответ таков: это не работает так, как написано в настоящее время. Если два потока вводят метод next: одновременно, они оба могут получить одно и то же значение начального числа и оба возвращать одно и то же значение.
Что бы я сделал, так это забыл об упаковке числа в объект NSNumber и просто поместил код в next: и setSeed: в блоках @synchronized
// randomSeed is a long long ivar
-(void) setSeed:(long long) seed1
{
@synchronized(self)
{
randomSeed = (seed1 ^ multiplier) & mask;
}
}
-(int) next:(int)bits
{
int ret;
@synchronized(self)
{
long long oldseed, nextseed;
long long seed1 = randomSeed;
//do {
oldseed = seed1;
nextseed = (oldseed * multiplier + addend) & mask;
//} while (!seed.compareAndSet(oldseed, nextseed)); /* you won't need to do this atomically */
randomSeed = nextSeed;
///ret = (int)(nextseed >>> (48 - bits));
ret = (unsigned int)(nextseed >> (48 - bits));
}
return ret;
}
Я не могу комментировать, верен ваш алгоритм или нет.
Однако ваш метод инициализации должен вызывать [super init] следующим образом:
-(id) init
{
self = [super init];
if (self != nil)
{
// init stuff
}
return self;
}
Если вы ищете атомарные манипуляции, то есть коллекция функций OSAtomic. Эти функции позволяют выполнять различные операции с 32- и 64-битными целыми числами.
Похожие вопросы
Новые вопросы
java
Java — это высокоуровневый объектно-ориентированный язык программирования. Используйте этот тег, если у вас возникли проблемы с использованием или пониманием самого языка. Этот тег часто используется вместе с другими тегами для библиотек и/или фреймворков, используемых разработчиками Java.
static
const
?AtomicLong
- этоlong
с атомарным поведением. Это позволяет вам делать такие вещи, какgetAndIncrement()
из нескольких потоков, не сталкиваясь с проблемами неверных данных. (Например, если бы он просто работал сcount++; return count;
, возможно, что два разных потока увидят один и тот же результат от разных вызовов, даже если вы хотели, чтобы он был уникальным.)@synchronized()
директива? (почему я не уверен, что это имеет большой смысл, так это то, что в любом случае вы не сможете запланировать выполнение потоков для выполнения точно в том же порядке ... Все, что вы можете гарантировать, это то, что числа генерируются в том же порядке, но вы не можете воспроизвести поток, который будет вызывать Random, когда ...)