final Map states; public SafeStates() { states = new HashMap(); states.put("alaska", "AK"); states.put("alabama", "AL"); ... states.put("wyoming", "WY"); } public String getAbbreviation(String s) { return states.get(s); } 178 Это относится только к тем объектам, которые доступны только через fi n al поля создаваемого объекта.
} Листинг 16.8 Безопасность инициализации неизменяемых объектов Однако ряд небольших изменений в классе SafeStates отнимет у него потокобезопасность. Если бы переменная states не была объявлена как final, или если бы любой метод, отличный от конструктора, изменил содержимое экземпляра, безопасность инициализации была бы недостаточно сильной для безопасного доступа к классу SafeStates без синхронизации. Если бы класс SafeStates имел другие, не final, поля, другие потоки могли бы по-прежнему видеть неправильные значения этих полей. И разрешение объекту сбежать во время строительства, отменяет гарантию безопасности инициализации. Безопасность инициализации гарантирует видимость только тех значений, которые доступны через поля final на момент завершения работы конструктора. Для значений, доступных через поля, не являющиеся final, или значений, которые могут измениться после построения, для гарантии видимости необходимо использовать синхронизацию. 16.3 Итоги Модель памяти Java определяет, когда действия с памятью одного потока гарантированно будут видимы другому. Специфика включает в себя обеспечение того, чтобы операции были упорядочены частичным порядком, называемым happens-before, который задается на уровне отдельных операций памяти и синхронизации. При отсутствии достаточной синхронизации, при доступе потоков к совместно используемым данным, могут происходить очень странные вещи. Однако правила более высокого уровня, предлагаемые в главах 2 и 3 , такие как аннотация @GuardedBy и безопасная публикация, могут использоваться для обеспечения потокобезопасности, без необходимости касаться низкоуровневых деталей отношения happens-before. Приложение A Описание аннотаций We’ve used annotations such as @GuardedBy and @ThreadSafe to show how thread- safety promises and synchronization policies can be documented. This appendix documents these annotations; their source code can be downloaded from this book’s website. (There are, of course, additional thread-safety promises and implementation details that should be documented but that are not captured by this minimal set of annotations.) A.1 Аннотации уровня классов Мы используем три аннотации уровня класса, предназначенные для описания обещанного уровня потокобезопасности: @Immutable , @ThreadSafe и @NotThreadSafe . Аннотация @Immutable означает, конечно, что класс является неизменяемым и включает в себя аннотацию @ThreadSafe . Аннотация @NotThreadSafe опциональна - если класс не аннотирован как потокобезопасный, его следует считать не потокобезопасным, но если вы хотите сделать это ещё более очевидным, используйте аннотацию @NotThreadSafe Эти аннотации относительно ненавязчивы и полезны как пользователям, так и сопровождающим. Пользователи могут сразу увидеть, является ли класс потокобезопасным, а сопровождающие могут сразу увидеть, должны ли быть предварительно предоставлены гарантии потокобезопасности. Аннотации также полезны для третьей группы: инструменты. Статические инструменты анализа кода могут быть в состоянии проверить, что код соответствует контракту, указанному аннотацией, такому как проверка, что класс, аннотированный @Immutable фактически, является неизменяемым. A.2 Аннотации уровня полей и методов Приведенные выше аннотации уровня класса являются частью общедоступной документации по классу. Другие аспекты стратегии обеспечения потокобезопасности класса предназначены исключительно для разработчиков и не являются частью общедоступной документации. Классы, использующие блокировки, должны документировать, какие переменные состояния с помощью каких блокировок защищаются и какие блокировки используются для защиты этих переменных. Распространённым источником непреднамеренного внесения не потокобезопасности является ситуация, когда класс согласованно использует блокировку для защиты своего состояния, но позже подвергается изменению, с целью добавления новых переменных состояния, адекватно не защищённых блокировкой, или новых методов, не корректно использующих блокировку, для защиты существующих переменных состояния. Документирование информации о том, какие переменные защищаются какими блокировками, может помочь предотвратить оба типа пропусков. Аннотация @GuardedBy(lock) документирует, что поле или метод должны быть доступны только с определенной блокировкой. Аргумент lock определяет блокировку, которая должна удерживаться при доступе к аннотируемому полю или методу. Возможные значения lock : • Аннотация @GuardedBy("this") , означает внутреннюю блокировку вмещающего объекта (объекта, членом которого является метод или поле); • Аннотация @GuardedBy(" fieldName") , означает блокировку, связанную с объектом, на который ссылается именованное поле, внутреннюю блокировку (для полей, не ссылающихся на экземпляр Lock ) или явный экземпляр Lock (для полей, ссылающихся на экземпляр Lock ); • Аннотация @GuardedBy(" ClassName.fieldName") , подобна аннотации @GuardedBy("fieldName") , но ссылка на объект блокировки, удерживается в статическом поле другого класса; • Аннотация @GuardedBy(" methodName()") означает, что объект блокировки, возвращается при вызове именованного метода; • Аннотация @GuardedBy(" ClassName.class") , литерально означает объект Class именованного класса. Использование аннотации @GuardedBy для идентификации каждой переменной состояния, которая нуждается в блокировке и того, какая блокировка что защищает, может помочь в обслуживании и проверке кода, а также помочь инструментам автоматического анализа выявить потенциальные ошибки в потокобезопасности. Библиография Ken Arnold, James Gosling, and David Holmes. The Java Programming Language, Fourth Edition. Addison–Wesley, 2005. David F. Bacon, Ravi B. Konuru, Chet Murthy, and Mauricio J. Serrano. Thin Locks: Featherweight Synchronization for Java. In SIGPLAN Conference on Programming Language Design and Implementation, pages258–268,1998. URL http://citeseer.ist.psu.edu/bacon98thin.html Joshua Bloch. Effective Java Programming Language Guide. Addison–Wesley, 2001. Joshua Bloch and Neal Gafter. Java Puzzlers. Addison–Wesley, 2005. Hans Boehm. Destructors, Finalizers, and Synchronization. In POPL ’03: Proceedings of the 30th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, pages262–272. ACM Press,2003. URL http://doi.acm.org/10. 1145/604131.604153 Hans Boehm. Finalization, Threads, and the Java Memory Model. JavaOne presentation, 2005. URL http://developers.sun.com/learning/ javaoneonline/2005/coreplatform/TS-3281.pdf Joseph Bowbeer. The Last Word in Swing Threads, 2005. URL http://java. sun.com/products/jfc/tsc/articles/threads/threads3.html Cliff Click. Performance Myths Exposed. JavaOne presentation, 2003. Cliff Click. Performance Myths Revisited. JavaOne presentation, 2005. URL http://developers.sun.com/learning/javaoneonline/2005/coreplatform/ TS-3268.pdf Martin Fowler. Presentation Model, 2005. URL http://www.martinfowler.com/ eaaDev/PresentationModel.html Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. Design Pat-terns. Addison–Wesley,1995. Martin Gardner. The fantastic combinations of John Conway’s new solitaire game ’Life’. Scientific American, October 1970. James Gosling, Bill Joy, Guy Steele, and Gilad Bracha. The Java Language Specification, Third Edition. Addison–Wesley,2005. Tim Harris and Keir Fraser. Language Support for Lightweight Transactions. In OOPSLA ’03: Proceedings of the 18th Annual ACM SIGPLAN Conference on Object-Oriented Programming, Systems, Languages, and Applications, pages388– 402. ACM Press, 2003. URL http://doi.acm.org/10.1145/949305.949340 Tim Harris, Simon Marlow, Simon Peyton-Jones, and Maurice Herlihy. Compos-able Memory Transactions. In PPoPP ’05: Proceedings of the Tenth ACM SIG-PLAN Symposium on Principles and Practice of Parallel Programming, pages48–60. ACM Press, 2005. URL http://doi.acm.org/10.1145/1065944.1065952
Maurice Herlihy. Wait-Free Synchronization. ACM Transactions on Programming Languages and Systems,13(1):124–149,1991. URL http://doi.acm.org/10. 1145/114005.102808 Maurice Herlihy and Nir Shavit. Multiprocessor Synchronization and Concurrent Data Structures. Morgan-Kaufman,2006. C. A. R. Hoare. Monitors: An Operating System Structuring Concept. Communications of the ACM,17(10):549–557,1974. URL http://doi.acm.org/10.1145/ 355620.361161 David Hovemeyer and William Pugh. Finding Bugs is Easy. SIGPLAN Notices, 39 (12):92–106, 2004. URL http://doi.acm.org/10.1145/1052883.1052895 Ramnivas Laddad. AspectJ in Action. Manning, 2003. Doug Lea. Concurrent Programming in Java, Second Edition. Addison–Wesley, 2000. Doug Lea. JSR-133 Cookbook for Compiler Writers. URL http://gee.cs. oswego.edu/dl/jmm/cookbook.html J. D. C. Little. A proof of the Queueing Formula L = λW". Operations Research, 9: 383 –387, 1961. Jeremy Manson, William Pugh, and Sarita V. Adve. The Java Memory Model. In POPL ’05: Proceedings of the 32nd ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, pages378–391. ACM Press,2005. URL http://doi.acm.org/10.1145/1040305.1040336 George Marsaglia. XorShift RNGs. Journal of Statistical Software, 8(13), 2003. URL http://www.jstatsoft.org/v08/i14 Maged M. Michael and Michael L. Scott. Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms. In Symposium on Principles of Distributed Computing, pages267–275,1996. URL http://citeseer. ist.psu.edu/michael96simple.html Mark Moir and Nir Shavit. Concurrent Data Structures, In Handbook of Data Structures and Applications, chapter47. CRC Press,2004. William Pugh and Jeremy Manson. Java Memory Model and Thread Specification, 2004. URL http://www.cs.umd.edu/pugh/java/memoryModel/jsr133.pdf M. Raynal. Algorithms for Mutual Exclusion. MIT Press, 1986. William N. Scherer, Doug Lea, and Michael L. Scott. Scalable Synchronous Queues. In 11th ACM SIGPLAN Symposium on Principles and Practices of Parallel Programming (PPoPP),2006. R. K. Treiber. Systems Programming: Coping with Parallelism. Technical Report RJ 5118, IBM Almaden Research Center, April 1986.
Andrew Wellings. Concurrent and Real-Time Programming in Java. John Wiley & Sons, 20
|