Синхронизация работы с условностями? Как я могу сделать этот код производительным и поточно-ориентированным? - PullRequest
1 голос
/ 12 февраля 2012

С учетом следующего кода:

public class SomeClass {

  private boolean shouldBlock = false;
  private Object resource;

  public void handleDrawRequest(Canvas canvas) {
    if (!shouldBlock && resource == null)
    {
       shouldBlock = true;
       loadTheResource();  //which takes awhile
       shouldBlock = false;
    }
    else if (shouldBlock && resrouce == null)
    {
       return;  //another thread is taking care of the loading of the resource
                //and its not ready yet, so just ignore this request
    }

    drawResourceOn(canvas);
  }
}

Как я могу сделать этот поток кода безопасным? Я пытаюсь выполнить один и только один поток для загрузки ресурса, в то время как любой другой поток, пытающийся одновременно получить доступ к этому коду, будет отброшен (например, следуйте логике «else if») до загрузки ресурса. Может быть много потоков, пытающихся получить доступ к этому коду одновременно, и я не хочу синхронизировать весь метод, и у меня накапливается целый стек потоков.

Ответы [ 2 ]

4 голосов
/ 12 февраля 2012

С дважды проверено неблокирование блокировка:

public class SomeClass {

    private Lock lock = new Lock();
    private volatile Object resource;

    public void handleDrawRequest(Canvas canvas) {
        if( resource==null ) {
            if( lock.tryLock() ) {
                try {
                    if( resource==null )
                        resource = loadResource();
                }
                finally {
                    lock.unlock();
                }
            }
            else {
                return;
            }
        }
        drawResourceOn(canvas);
    }
}

Если вы не сделаете resource volatile, потоки могут кешироватьсяэто и может никогда не прочитать обновленное значение.В частности, вторая нулевая проверка всегда будет возвращать true, даже если ресурс был загружен после первой.

2 голосов
/ 12 февраля 2012

Вы ищете AtomicBoolean

public class SomeClass {
  // AtomicBolean defaults to the value false.
  private AtomicBoolean loadingResource = new AtomicBoolean();
  private volatile Object resource;

  public void handleDrawRequest(Canvas canvas) {
    if (resource == null) {
      if (loadingResource.compareAndSet(false, true)) {
        loadTheResource();  //which takes awhile
      } else {
        //another thread is taking care of the loading of the resource
        //and its not ready yet, so just ignore this request
        return;  
      }
    } else {
      drawResourceOn(canvas);
    }
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...