`
lvhuiqing
  • 浏览: 244894 次
  • 性别: Icon_minigender_1
  • 来自: 沈阳
社区版块
存档分类
最新评论

Chapter 2. Thread Safety(线程安全)

阅读更多
Chapter 2. Thread Safety(线程安全)
Perhaps surprisingly, concurrent programming isn't so much about threads or locks, any more than civil engineering is about rivets and I-beams. Of course, building bridges that don't fall down requires the correct use of a lot of rivets and I-beams, just as building concurrent programs require the correct use of threads and locks. But these are just mechanisms means to an end. Writing thread-safe code is, at its core, about managing access to state, and in particular to shared, mutable state.
可能有些奇怪,并发程序设计最为形象的例子并不是线程与锁,而是土木工程中的柳丁和I型槽。如果不想让一座正在建造中的桥梁垮掉的话,就必须正确的使用I型槽和柳丁,就如同良好的并发程序设计要求正确的使用线程和锁。这些都是达到目的最基本的机制。所谓线程安全的实质上就是管理对状态的访问,尤其是那些被共享的,并且可变的状态。
Informally, an object's state is its data, stored in state variables such as instance or static fields. An object's state may include fields from other, dependent objects; a HashMap's state is partially stored in the HashMap object itself, but also in many Map.Entry objects. An object's state encompasses any data that can affect its externally visible behavior.
一个对象的状态是指他的数据,这些数据被保存在状态变量中,比如实例域和静态域。一个对象的状态可能包括其他对象的域,这与他所依赖的对象有关。HashMap的对象只有一部分在HashMap对象本身中,还有一部分在Map.Entry对象中。一个对象的状态包括哪些可以影响其外部课件的行为的数据。
By shared, we mean that a variable could be accessed by multiple threads; by mutable, we mean that its value could change during its lifetime. We may talk about thread safety as if it were about code, but what we are really trying to do is protect data from uncontrolled concurrent access.
如果说一个变量是共享的,那就意味着我们可以从多个线程中去访问他们。如果说一个变量时可变的,那意味在变量的生命周期中,该变量是有可能会发生变化的。我们可能会觉得线程安全是与代码相关的,但实质上,我们真正关注的是对被保护的数据不会被没有控制的并发程序访问。
Whether an object needs to be thread-safe depends on whether it will be accessed from multiple threads. This is a property of how the object is used in a program, not what it does. Making an object thread-safe requires using synchronization to coordinate access to its mutable state; failing to do so could result in data corruption and other undesirable consequences.
一个对象是否需要是现成安全的取决于该对象是否会被多个线程并发访问。这与该对象是如何被使用的相关。如果要把一个对象设计成线程安全的,要求使用同步机制来协调那些访问其可变状态的线程。如果做不到这一点,就可能会出现脏数据和其他不期望得到的结果。
Whenever more than one thread accesses a given state variable, and one of them might write to it, they all must coordinate their access to it using synchronization. The primary mechanism for synchronization in Java is the synchronized keyword, which provides exclusive locking, but the term "synchronization" also includes the use of volatile variables, explicit locks, and atomic variables.
在任何时候,如果有多个线程会访问一个给定的状态变量,只要其中有一个会改写该变量,就必须使用同步机制来协调这些线程。Java中最为常见的同步机制是synchronized关键字,synchronized关键字可以提供一个排他锁。同时,java中还包括别的同步机制,比如volatile变量,显式锁、和原子变量。
You should avoid the temptation to think that there are "special" situations in which this rule does not apply. A program that omits needed synchronization might appear to work, passing its tests and performing well for years, but it is still broken and may fail at any moment.
你最好不要心存侥幸的认为在某些情况下有一些情形是特殊的,以至于上一条原则可以不适用。一个违反同步原则的程序可能在很长时间内工作良好、也能够通过测试,但是还是有可能在某个时刻出现严重后果。
If multiple threads access the same mutable state variable without appropriate synchronization, your program is broken. There are three ways to fix it:
• Don't share the state variable across threads;
• Make the state variable immutable; or
• Use synchronization whenever accessing the state variable.
如果多个线程访问相同的状态可变的变量,而没有使用恰当的同步机制,你的程序有可能被破坏,你有三种途径可以修正这种bug:
• 不要在线程间同步变量;
• 使得状态变量是不可变的;
• 无论何时访问的时候状态变量的时候,都是用同步机制。

If you haven't considered concurrent access in your class design, some of these approaches can require significant design modifications, so fixing the problem might not be as trivial as this advice makes it sound. It is far easier to design a class to be thread-safe than to retrofit it for thread safety later.
如果你在设计类的时候不慎没有考虑到同步的问题,以上的几个方法可能会导致很大程度的设计变更。因此有时候修正该问题不如重新设计一个线程安全的新类来的容易。
In a large program, identifying whether multiple threads might access a given variable can be complicated. Fortunately, the same object-oriented techniques that help you write well-organized, maintainable classes such as encapsulation and data hiding can also help you create thread-safe classes. The less code that has access to a particular variable, the easier it is to ensure that all of it uses the proper synchronization, and the easier it is to reason about the conditions under which a given variable might be accessed. The Java language doesn't force you to encapsulate state it is perfectly allowable to store state in public fields (even public static fields) or publish a reference to an otherwise internal object but the better encapsulated your program state, the easier it is to make your program thread-safe and to help maintainers keep it that way.
在一个大型程序中,识别出一个变量是否会被多线程访问有时候是很复杂的。幸运的是,一些面向对象技术可以使你编写组织良好的、可维护的线程安全类。这些技术包括封装和代码隐藏等等。可以访问某一个特定的变量的代码越少,保证这个特定变量被同步访问的就越容易,也就越容易搞清楚在什么情况下该特定变量可以被访问。Java语言不会强制你去封装变量,它允许你把状态设置成public,甚至是static public。或者发布对外部对象发布一个引用。但是你的状态封装的越好,你的程序的线程安全性就会越好。
When designing thread-safe classes, good object-oriented techniques encapsulation, immutability, and clear specification of invariants are your best friends.
当需要设计线程安全类的时候,良好的面向对象的封装技术:持久不变性、清晰的常量定义是你最好的工具。
There will be times when good object-oriented design techniques are at odds with real-world requirements; it may be necessary in these cases to compromise the rules of good design for the sake of performance or for the sake of backward compatibility with legacy code. Sometimes abstraction and encapsulation are at odds with performance although not nearly as often as many developers believe but it is always a good practice first to make your code right, and then make it fast. Even then, pursue optimization only if your performance measurements and requirements tell you that you must, and if those same measurements tell you that your optimizations actually made a difference under realistic conditions. [1]
[1] In concurrent code, this practice should be adhered to even more than usual. Because concurrency bugs are so difficult to reproduce and debug, the benefit of a small performance gain on some infrequently used code path may well be dwarfed by the risk that the program will fail in the field.
良好的面向对象的技术也有可能存在与现实世界不耦合的情况。遇到这种情况就需要在设计良好的原则和性能之间或者和兼容遗传的代码之间取得平衡。有时候,抽象和封装可能会与性能存在冲突,尽快不是每个人开发者都这样认为,但是通常我们都应该首先是你的代码能够正确的运行,然后再考虑如何加快运行速度。你应该在你的性能测试和需求的驱动下才去追求优化,或者在实际运行环境下的测试要求你不得不这么做。
在并发编程过程中,这条实践原则会显得更加重要。因为并发bug非常难以被发现和修正。一些细微的性能提升所带来的代价有可能是整个软件的灾难性后果。
If you decide that you simply must break encapsulation, all is not lost. It is still possible to make your program thread-safe, it is just a lot harder. Moreover, the thread safety of your program will be more fragile, increasing not only development cost and risk but maintenance cost and risk as well. Chapter 4 characterizes the conditions under which it is safe to relax encapsulation of state variables.
如果你最终决定不得不破坏封装,你也还有一线生机来保证你的应用程序做到线程安全,当然这样做会变得有些困难。而且,你的线程安全性也将会变得更加脆弱,这将会增加开发和维护的成本和风险。第四章中将会描述在何种情况下即使破坏封装也能够得到安全保证。
We've used the terms "thread-safe class" and "thread-safe program" nearly interchangeably thus far. Is a thread-safe program one that is constructed entirely of thread-safe classes? Not necessarily a program that consists entirely of thread-safe classes may not be thread-safe, and a thread-safe program may contain classes that are not thread-safe. The issues surrounding the composition of thread-safe classes are also taken up in Chapter 4. In any case, the concept of a thread-safe class makes sense only if the class encapsulates its own state. Thread safety may be a term that is applied to code, but it is about state, and it can only be applied to the entire body of code that encapsulates its state, which may be an object or an entire program.
到目前为止,我们一直在交替使用“线程安全类”和“线程安全程序”这样的字眼。让我们来考虑这样一个问题:“线程安全程序就是一个由所有线程安全类组成的程序吗”?。一个线程安全的应用程序并不一定都是由线程安全的类组成的。线程安全的应用程序中也可能包含非线程安全的类。围绕线程安全类组成的话题也将会在第四章中进行。无论如何,线程安全类这个概念只有在该类本身封装了其状态的情况下才会有意义。线程安全可以是一个适用于代码的概念,但他是关于与状态相关的,换句话说,它只适用于包含状态的代码,这样的代码可以是一个类,也可能是整个程序。
0
1
分享到:
评论
1 楼 bushuang1983 2011-01-20  
怎么不继续翻译了。翻译的蛮好的

相关推荐

Global site tag (gtag.js) - Google Analytics