Многопоточность головной боли.Джава.Возвращаемые значения - PullRequest
0 голосов
/ 26 мая 2011

Привет, ребята, у меня есть следующее.

class a extends Thread    
{
    public synchronized BigInteger getUniqueID()
    {
        BigInteger aUniqueID = new BigInteger(getUniqueKeyFromDatabase);
        return aUniqueID;
    }   
}

class b extends a
{
    public run()
    {
        BigInteger uniquieID = getUniqueID();       
        // store UniqueID in another database table with other stuff
     }
}

И я получаю дубликат уникального идентификатора, хранящийся в таблице базы данных. Я предполагаю, потому что uniqieID изменяется в этой многопоточной среде.

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

Любая помощь будет принята с благодарностью, так как мой хрупкий ум сейчас искажен!

Приветствия

Alan

Ответы [ 5 ]

2 голосов
/ 26 мая 2011

BigInteger - это (из JavaDocs )

Неизменяемое целое число произвольной точности

Так что исключается любое мутирование BigIntegerобъект.Я бы посмотрел в getUniqueKeyKeyFromDatabase

2 голосов
/ 26 мая 2011

You getUniqueKeyFromDatabase () должен быть методом, который не будет возвращать одно и то же значение дважды. Все остальное не имеет значения.

Каждый поток имеет свою собственную копию локальных переменных, если они не являются общими.

Кстати: не расширяйте Thread, это плохая практика, которая часто приводит к путанице.

1 голос
/ 26 мая 2011

Ваша проблема в том, что вы ничего не синхронизируете.Метод getUniqueID () в классе A синхронизируется на своем собственном неявном мониторе.Но это означает, что каждый раз, когда вы создаете новый поток, вы синхронизируете каждый поток самостоятельно.Имеет ли это смысл?

Вам нужно синхронизировать некоторые общие переменные.Быстрое исправление, чтобы проиллюстрировать эту мысль (но на самом деле не используйте это на практике): В приведенном ниже примере все ваши потоки синхронизируются на одном и том же объекте (общая статическая).

0 голосов
/ 26 мая 2011

У вас должна быть проблема с методом, который возвращает уникальный идентификатор. Чтобы обеспечить уникальность ваших идентификаторов для каждого объекта, используйте что-то вроде ниже, например, в вашем классе.

PS: имена классов должны начинаться с заглавных букв. Также, как предлагает @Peter Lawrey, реализуйте Runnable вместо расширения Thread.

    private static int nextId = 0;
    protected int id;

    public a(){
       this.id = getNextId();
    }
    private static int getNextId(){
        return nextId++;
    }
0 голосов
/ 26 мая 2011

Скорее всего, модификатор synchronized для getUniqueID() не имеет смысла, так как вы не изменяете там никакого состояния. Он также не защищает getUniqueKeyFromDatabase(), поскольку он синхронизируется с экземпляром. Это означает, что каждый поток выполняется без синхронизации с другими.

Вы можете попробовать, если

public BigInteger getUniqueID() {
   synchronized (a.class) {
      BigInteger aUniqueID = new BigInteger(getUniqueKeyFromDatabase);
      return aUniqueID;
   } 
}

Работает лучше для вас. Если это так, вам следует подумать о дизайне вашей базы данных (или о том, что происходит в getUniqueKeyFromDatabase). Синхронизация должна выполняться базой данных, а не кодом клиента.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...