2014-09-29 3 views
12

Я работаю над кодом Java, мне нужно реализовать потоки в нем. Я проходил через JAVA 8 API, и я узнал о Stamped Locks. Может ли кто-нибудь сказать мне, почему использовать StampedLocks в многопоточности?Что такое StampedLock в Java?

Заранее спасибо.

+2

Что такое _normal multithreading_? – Keppil

+0

@ SimY4 Я только что прочитал о Stamped locks только в документе. Затем я обдумал это. Но я не понимаю, почему мы должны его использовать. Должно быть какое-то преимущество использования Stamped locks, поэтому Oracle представляет его в java 8. – Mohit

+0

@ Keppil Я отредактировал свой вопрос. Спасибо, что исправил меня. – Mohit

ответ

14

StampedLock является альтернативой использованию ReadWriteLock (реализуется ReentrantReadWriteLock). Основные различия между StampedLock и ReentrantReadWriteLock таково:

  • StampedLocks позволяет оптимистическую блокировку для операций чтения
  • ReentrantLocks реентерабелен (StampedLocks не)

Так что если у вас есть сценарий, где у вас есть раздор (в противном случае вы можете использовать synchronized или просто Lock), и больше читателей, чем писателей, использование StampedLock может значительно повысить производительность.

Однако вы должны измерить эффективность, основанную на вашем конкретном прецеденте, прежде чем перейти к выводам.

Heinz Kabutz написал о StampedLocks in his newsletter, а также сделал a presentation about performance.

+0

Спасибо, теперь я знаю случай, когда я могу его использовать, и получил четкое представление об этом. – Mohit

+0

@Mohit, перейдите по ссылке, чтобы понять, что StampedLock немного лучше: https://dzone.com/articles/a-look-at-stampedlock – Roshan

+0

Статья Хайнца прекрасно объяснила все механизмы синхронизации коротким примером. Благодаря! –

5

Документация API для java.util.concurrent.locks.StampedLock говорит:

StampedLocks предназначены для использования в качестве внутренних коммуникаций в разработке поточно-компонентов. Их использование зависит от знания внутренних свойств данных, объектов и методов, которые они защищают. Они не являются реентерабельными, поэтому заблокированные тела не должны вызывать другие неизвестные методы, которые могут попытаться повторно приобрести блокировки (хотя вы можете передать штамп другим методам, которые могут его использовать или преобразовать). Использование режимов блокировки чтения зависит от того, связаны ли соответствующие секции кода без побочных эффектов. Неопределенные оптимистические разделы чтения не могут вызывать методы, которые, как известно, не допускают потенциальных несоответствий. Штампы используют конечные представления и не являются криптографически безопасными (т. Е. Допустимый штамп может быть допустимым). Значения штампа могут быть возвращены после (не раньше) одного года непрерывной работы. Штамп, удерживаемый без использования или проверки дольше, чем этот период, может не соответствовать правильному правилу. StampedLocks являются сериализуемыми, но всегда десериализуются в исходное разблокированное состояние, поэтому они не полезны для удаленной блокировки.

например. -

class Point { 
    private double x, y; 
    private final StampedLock sl = new StampedLock(); 

    void move(double deltaX, double deltaY) { // an exclusively locked method 
    long stamp = sl.writeLock(); 
    try { 
     x += deltaX; 
     y += deltaY; 
    } finally { 
     sl.unlockWrite(stamp); 
    } 
    } 

    double distanceFromOrigin() { // A read-only method 
    long stamp = sl.tryOptimisticRead(); 
    double currentX = x, currentY = y; 
    if (!sl.validate(stamp)) { 
     stamp = sl.readLock(); 
     try { 
      currentX = x; 
      currentY = y; 
     } finally { 
      sl.unlockRead(stamp); 
     } 
    } 
    return Math.sqrt(currentX * currentX + currentY * currentY); 
    } 

    void moveIfAtOrigin(double newX, double newY) { // upgrade 
    // Could instead start with optimistic, not read mode 
    long stamp = sl.readLock(); 
    try { 
     while (x == 0.0 && y == 0.0) { 
     long ws = sl.tryConvertToWriteLock(stamp); 
     if (ws != 0L) { 
      stamp = ws; 
      x = newX; 
      y = newY; 
      break; 
     } 
     else { 
      sl.unlockRead(stamp); 
      stamp = sl.writeLock(); 
     } 
     } 
    } finally { 
     sl.unlock(stamp); 
    } 
    } 
} 
1

StampedLock поддерживает блокировки чтения и записи. В отличие от ReadWriteLock методы блокировки StampedLock возвращают штамп, представленный длинным значением. Вы можете использовать эти штампы, чтобы либо отпустить блокировку, либо проверить, действительно ли блокировка действительна. Кроме того, штампованные замки поддерживают другой режим блокировки, называемый оптимистичной блокировкой.

ExecutorService executor = Executors.newFixedThreadPool(2); 
     Map<String, String> map = new HashMap<>(); 
     StampedLock lock = new StampedLock(); 

     executor.submit(() -> { 
      long stamp = lock.writeLock(); 
      try { 
       Thread.sleep(100); 
       map.put("test", "INDIA"); 
      } catch (Exception e) { 
      } finally { 
       lock.unlockWrite(stamp); 
      } 
     }); 

     Runnable readTask =() -> { 
      long stamp = lock.readLock(); 
      try { 
       System.out.println(map.get("test")); 
       Thread.sleep(100); 
      } catch (Exception e) { 
      } finally { 
       lock.unlockRead(stamp); 
      } 
     }; 

     executor.submit(readTask); 
     executor.submit(readTask); 

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

executor.submit(() -> { 
      long stamp = lock.tryOptimisticRead(); 
      try { 
       System.out.println("Optimistic Lock Valid: " + lock.validate(stamp)); 
       Thread.sleep(100); 
       System.out.println("Optimistic Lock Valid: " + lock.validate(stamp)); 
       Thread.sleep(1000); 
       System.out.println("Optimistic Lock Valid: " + lock.validate(stamp)); 
      } catch (Exception e) { 
      } finally { 
       lock.unlock(stamp); 
      } 
     }); 

     executor.submit(() -> { 
      long stamp = lock.writeLock(); 
      try { 
       System.out.println("Write Lock acquired"); 
       Thread.sleep(100); 
      } catch (Exception e) { 
      } finally { 
       lock.unlock(stamp); 
       System.out.println("Write done"); 
      } 
     }); 

Оптимистическая блокировка чтения приобретается путем вызова tryOptimisticRead(), которая всегда возвращает печать без блокировки текущего потока, независимо от того, если замок на самом деле имеется. Если активна блокировка записи активна, возвращаемый штамп равен нулю. Вы всегда можете проверить, действителен ли штамп, вызвав lock.validate (штамп).