Java синхронизированный объект? - PullRequest
3 голосов
/ 22 декабря 2011

У меня есть класс в Java, который читает пакеты UDP и помещает их в объект (в основном в бесконечном цикле).Затем к этому объекту обращаются в нескольких отдельных потоках, но, очевидно, поскольку он заполняется одновременно, все эти методы получения / установки находятся в синхронизированных методах.Проблема в том, что сейчас у этих геттеров есть такой код:

public synchronized SomeObject exampleGetter() {
    if(this.isReceiving)
        return oldCachedObject;
    else
        return currentObject;
}

Очевидно, что это не совсем лучший способ сделать что-то, поэтому как мне написать методы (множество разных), которые полностью блокируютобъект к одному потоку за один раз и блокировать другие (включая поток, который создал объект в первую очередь)?Я посмотрел на синхронизированные блоки, но меня немного смущает, какой эффект имеет «объект блокировки», это тот объект, который имеет доступ к блоку в данный момент времени?Любой совет будет принят во внимание.Спасибо!

Ответы [ 3 ]

5 голосов
/ 22 декабря 2011

Ключевое слово synchronized синхронизируется на всем экземпляре объекта, а не только на установщике.Я предпочел бы пойти на тонкозернистую стратегию блокировки или лучше ... использовать многопоточную структуру данных, где вы храните и получаете полученные данные.Мне лично нравится BlockingQueue<T>, где T - это тип данных, которые вы получаете в сети.

Предположим, вы получаете Object s через сокет:

public class ReceivedDataHolder{
    BlockingQueue<Object> dataBuffer = new LinkedBlockingQueue<Object>();
    //...
    public void dataReceived(Object data){
       dataBuffer.offer(data);
    } 

    public Object getReceivedData(){
       return dataBuffer.take();
    }
}

И в своем сокете вы можете делать это всякий раз, когда получаете данные:

receivedDataHolder.dataReceived(object);

Любой поток, который хочет получить данные, должен сделать:

receivedDataHolder.getReceivedData();

Этот последний вызов метода заблокирует вызывающий поток, пока в очереди не будет доступен элемент (проверьте this для получения более подробной информации.)

Надеюсь, это поможет

2 голосов
/ 22 декабря 2011
0 голосов
/ 22 декабря 2011

У всех объектов в java есть что-то, называемое внутренней блокировкой. Если какой-либо поток хочет выполнить какую-либо операцию над любым объектом, ему необходимо получить внутреннюю блокировку этого объекта. это гарантирует, что только один поток будет обрабатывать ваш блок кода в любой момент времени.

Поток может получить блокировку для любого объекта, если этот объект не заблокирован каким-либо другим потоком, если он заблокирован, поток будет ждать, пока другой поток не снимет блокировку с этого объекта.

если вы используете синхронизированный блок, ваш код будет выглядеть примерно так

public void SomeObject exampleGetter() {

synchronized(this)
{


if(this.isReceiving)
        return oldCachedObject;
    else
        return currentObject;


}

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

для получения дополнительной информации о синхронизированных блоках, методах и внутренних блокировках, обратитесь к http://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html

Надеюсь, это вам помогло:)

...