Third, the combination of objects

一、设计线程安全的类

通过使用封装技术,可以使得在不对整个程序进行分析的情况下就可以 判断一个类是否是线程安全的。

在设计线程安全类的过程中,需要包含以下三个基本要素:

  • Identify all variables including the state of the object.
  • Find out the condition of invariance constraints state variables.
  • Establish concurrent access management strategies like state.

要分析对象的状态,首先从对象的域开始。如果对象中所有的域都是基本类型的变量,那 么这些域将构成对象的全部状态。于含有n个基本类型域的对象,其状态就是这些域构成的n元组。 例如,二维点的状态就是它的坐标值(x, y)。如果在对象的域中引用了其他对象,那么该对象 的状态将包含被引用对象的域。例如,LinkedList的状态就包括该链表中所有节点对象的状态。

Synchronization strategy (Synchronization Policy) defines access operations to its state after case of how not contrary to the object in the same experimental conditions or conditions of collaborate. Synchronization strategy sets out how to combine immutability, thread sealing and locking mechanisms together to maintain security thread, and which also provides for a variable which is protected by a lock. To ensure that developers can analyze and maintain the class, it must be written as a formal document synchronization strategy.

  • 收集同步需求

To ensure thread safety class, we need to ensure that its invariance conditions will not be damaged in case of concurrent access, which requires them to infer the state. Object variable has a state space, that is, all possible values. State space, the easier determination of the state of the thread. The final type field use, the more likely subject analysis process can be simplified state. (In extreme cases, only a single immutable object state.)

在许多类中都定义了一些不可变条件,用于判断状态是有效的还是无效的。Counter The value of a variable type is long, the state space of Long.MAX_VALUE from Long.MIN_VALUE to, but there is a value in the Counter limited in range, that can not be negative.

同样,在操作中还会包含一些后验条件来判断状态迁移是否是有效的。If the current state of the Counter is 17, then the next state can only be effective 18. When the next state of the need to rely on the current state, this operation must be a complex operation. Not all operations will impose restrictions on state transitions, e.g., when a variable is updated to save the current temperature, a state before the variable does not affect the results.

Since the invariant conditions and conditions of the posterior various constraints imposed on the state and state transitions, thus requiring additional synchronization package. If some state is invalid, it must be encapsulated underlying state variables, or client code may make the object in an invalid state. If an invalid state in the presence of a conversion operation, then the operation must be atomic. Further, if the constraint is not applied in this class, then the package may be relaxed or sequence of other needs, in order to obtain greater flexibility or performance.

If you do not know the object invariance condition you and posterior condition, so long can not ensure thread safety. Tuned to meet various constraints on the effective value or state transition of state variables, and need the help of encapsulation atoms.

  • 依赖状态的操作

Invariance condition like a posteriori constraint condition which states and state transitions are valid on the object. In the method of some object also includes some state-based 先验条件(Precondition)。, for example, an element can not be removed from the queue empty, before removing elements, must be in the queue ^ "non-empty" state. If there is a state based on a priori conditions comprise an operation, then the operation is called a dependent operating state.

In a single-threaded program, if an operation can not meet the a priori condition, then it can only fail. but在并发程序中,先验条件可能会由于其他线程执行的操作而变成真。在并发程序中要一直等到先验条件为真,然后再执行该操作。

In Java, waiting for some condition is true variety of built-in mechanisms (including mechanisms and wait for notification) are closely associated with the built-in locking mechanism, in order to use them correctly is not easy. Wait a priori in order to achieve true when the operation is performed, a more simple method is implemented by a state-dependent (e.g. blocking queue [Blocking Queue] or semaphore [Semaphore]) existing class library the behavior of.

  • 状态的所有权

When defining which variables will form the state of the object, considering only data objects have. Ownership (Ownership) has not been fully reflected in Java, but belongs to a feature class design. If you assign and populate a HashMap object, then create the equivalent of more than one object: HashMap object that contains multiple objects in the HashMap object, as well as internal objects that may be contained in Map.Entry. HashMap object logic state includes all Map. Entry objects and internal objects, even though they are some independent objects.

In many cases, the ownership of the package are always interrelated: Object has its packaged state, and vice versa is also true, i.e., it has the ownership status of the package. The owner of the state variables will determine which protocol uses a lock to maintain the integrity of the state variables. Ownership means control. However, if you publish a reference to an object variable, then it no longer has exclusive control of, at most, "shared control." For transfer from the constructor or the object coming from the process, typically do not own these objects class, unless they are specifically designed for proprietary methods (e.g., synchronous wrapper container factory method) for the transfer of objects passed in.

Containers typically exhibit a form of "isolated ownership", wherein the container class has its own state, the state of each client code owns the object container. Servlet ServletContext frame is one example. ServletContext provides a service similar to the Map object container in the form of Servlet, in the ServletContext can be registered by name (setAttribute) or acquired (getAttribute) application object. ServletContext object is achieved by the Servlet container must be thread-safe, because it is sure to be accessed simultaneously by multiple threads. When calling setAttribute and get Attribute, Servlet does not require synchronization, but using the object stored in the ServletContext, you may need to use synchronous. These objects are owned by the application, Servlet container just keep them for applications |. Like all shared objects, they must be shared safely. In order to prevent multiple threads access the same object concurrently generated when the mutual interference, these objects should either be thread-safe objects, or the fact that the object is immutable, or by the locks to protect.

二、实例封闭

If an object is not thread safe, then it can be safely used in multithreaded programs through a variety of techniques. You can only be sure that the objects (thread closed) by a single thread access, or to protect all access to the object through a lock.

封装简化了线程安全类的实现过程,它提供了一种实例封闭机制(Instance Confinement), 通常也简称为“封闭” [CPJ 2.3.3]。When an object is encapsulated into another object, it is possible to access all the encapsulated object code paths are known. Compared to the entire program can be accessed by the object easier to analyze the code. By closing mechanism combined with an appropriate locking strategy, we can ensure that the objects in a thread-safe way to use a non-thread-safe.

将数据封装在对象内部,可以将数据的访问限制在对象的方法上,从而更容易确保线程在访问数据时总能持有正确的锁。

被封闭对象一定不能超出它们既定的作用域。One example of objects can be closed (e.g., as a private member of the class) in the class, or enclosed within a scope (e.g., as a local variable), or in another thread (e.g., in a subject from a thread closure a method of passing to another method, the object is not shared among multiple threads). Of course, the object itself can not escape - escape situation occurs because the developer is usually due to an object beyond the scope established at the time of publication object.

封闭机制更易于构造线程安全的类,因为当封闭类的状态时,在分析类的线程安全 性时就无顼检查整个程序。

  • Java监视器模式

Thread closed principle from its logical conclusion can be drawn Java monitor mode.遵循Java监视器模式的对象会把对象的所有可变状态都封装起来,并由对象自己的内置锁来保护。

In many uses of the Java class monitor mode, for example, Vector and Hashtable. In some cases, the program requires a more sophisticated synchronization strategy.

Java Monitor mode only is a method of writing code,对于任何一种锁对象,只要自始至终都使用该锁对象,都可以用来保护对象的状态。

public class PrivateLock {

    private final Object myLock = new Object();

    Widget widget;

    public void someMethod() {
        synchronized(myLock) {
            // 访问或修复Widget的状态
        }
    }
}

三、线程安全性的委托

Most objects are grouped objects. When a class built from scratch, or a plurality of thread-safe composition class as a class, Java monitor mode is useful. However, if the class of the individual components are already thread-safe, what would happen? Do we need to add an extra layer of security thread? The answer is "as appropriate."在某些情况下,通过多个线程安全类组合而成的类是线程安全的),而在某些情况下,这仅仅是一个好的开端)。

  • 独占的状态变量

我们可以将线程 安全性委托给多个状态变量,只要这些变量是彼此独立的,即组合而成的类并不会在其包含的 多个状态变量上增加任何不变性条件。

如果一个类是由多个独立且线程安全的状态变量组成,并且在所有的操作中都不包 含无效状态转换,那么可以#线程安全性委托给底层的状态变量。

如果一个状态变量是线程安全的,并且没有任何不变性条件来约束它的值,在变量的操作上也不存在任何不允许的状态转换,那么就可以安全地发布这变量。

四、在现有的线程安全类中添加功能

Java class library contains many useful "base module" category. In general, we should prefer to reuse the existing class rather than creating a new class: 重用能降低开发工作量、开发风险(因为现有的类都已经通过测试) 以及维护成本。Sometimes, an existing thread-safe classes can support all the operations we need, but more often, existing class can only support most of the operations, then you need to add a new operation without destroying Qian Cheng security.

  • 客户端加锁机制

For the Collections.synchronizedListArrayList package, these two methods - 在原始类中添加一个方法或者对类进行扩展都行不通,because the client does not know the type of the code returned List object in the synchronous wrapper process plant.第三种策略是扩展类的功能,但并不是扩展类本身,而是将扩展代码放入一个“辅助类”中。

  • 组合

When the atomic operation is added to a conventional class, there is a better way: composition (Composition).

public class ImprovedList<T> implements List<T> {


    private final List<T> list;

    public ImprovedList(List<T> list) {
        this.list = list;
    }

    public synchronized boolean putlfAbsent(T x) {
        boolean contains = list.contains(x);
        if (contains)
            list.add(x);
        return !contains;
    }

    public synchronized void clear() {

    }
	
	...............
}	

五、将同步策略文档化

Thread safety during maintenance, documentation is one of the most powerful (but also the most underutilized) tools. Users can be judged by whether or consult the documentation of a class is thread-safe, and maintenance personnel can also be understood by referring to one of the implementation strategy document, to avoid damage to safety during maintenance.
Description client code in the document need to know about thread safety assurance, as well as to maintain synchronization policy you need to know.


Guess you like

Origin blog.csdn.net/qq_27870421/article/details/90582751