"Pattern-oriented software Architecture, Patterns for Concurrent and networked Objects" Vol.2 notes

Source: Internet
Author: User

Gof's 23 classic models make design patterns a common language for programmers. "Pattern-oriented software Architecture, Patterns for Concurrent and networked Objects" Volume 2 mainly summarizes the four types of 16 design patterns in parallel systems. Here is an excerpt of finishing.

Service Access and Configuration Wrapper Facade

It wraps the underlying system-level APIs into an object-oriented, unified and portable interface. The system layer C interface, such as thread, Mutex, Condition Variable and socket, is not only portable but error-prone. High-level languages such as C + + can encapsulate some semantic rules (such as releasing locks when leaving scope, mutex/conition variable, etc.) through language features. Like Android, Looper,thread, mutexes can be seen as the application of this pattern.

Component Configurator

Implement dynamic loading and configuration of components. It consists of four main parts: Component provides a unified interface, specific components provide a specific type of implementation, Component repository manages all concrete components,component Configurator uses component repository to coordinate the configuration of specific components. such as the ServiceManager in Android uses this mode to manage the service in the system.

Interceptor

Allows an app to extend the framework by registering a service that conforms to a predetermined interface. In short, it is the hook function interface provided by the framework. First, the system gives the interceptor callback interface, and the application is responsible for implementing the specific interceptor. Similar to observer mode, specific interceptor can be registered with dispatcher, and then dispatcher receive the event, it will be distributed to all registered interceptor.

Extension Interface

Allows the same component to expose multiple interfaces, preventing interface from exploding. The main goal is to change the functionality of the component and not break the existing client code. The solution is to have the client access the component through a separate interface, rather than using a unified interface. For the same object, each client sees only the interfaces it needs. For example, Android 4.4 in the Bufferqueue class, both to achieve the producer interface and realize the consumer, different client picking, changes do not affect each other.

Event Handling Patterns Reactor (Dispatcher, Notifier)

For event-driven applications, reactor allows it to tap and distribute requests from more than one client. It can wait for events to arrive synchronously from one or more event sources, and decouple the branching and distribution mechanisms from the events that are applied. The disadvantage is that it has poor scalability because all operations are single-threaded and serially executed. such as the Looper in Android, there is also the Libev library, where the message loop is the implementation of reactor mode.

Proactor

Unlike reactor's pure passive wait mode, the application component in Proactor mode proactively initiates control and data flow by initiating one or more asynchronous operation requests. The tap and distribute of the service request is triggered by an asynchronous operation End event. It requires an OS support for asynchronous I/O, such as GetQueuedCompletionStatus () in Windows.

Asynchronous Completion Token (Active demultiplexing, Magic Cookie)

When the client initiates an asynchronous operation request to the service, an act is created. It is a closure of the completion handler, which contains all the information needed to specify completion handler. It is then passed along with the request to the service. The service will not modify it and will be passed back to the client when the application is completed. The MessageHandler in Android is an example of synchronizing the ACT variants.

Acceptor-connector

The Acceptor-connector mode decouples the connection and initialization from the service at a later point. In general, two factories acceptor and connector are used to create a connection for service handler. When the connection is established, the acceptor and connector factories initialize the corresponding service handler. Service handler can then Exchange data and perform operations through the transport handle, and no longer need to interact with acceptor or connector factories. For example, in Android, the client wants to connect to the Surfaceflinger by Composerservice to the Surfaceflinger request, Surfaceflinger returns surfacecomposerclient. Then surfacecomposerclient can communicate directly with the client in Surfaceflinger.

Synchronization Patterns Scoped Locking (Synchronized Block, Resource-acquisition-is-initialization, Guard, Execute Around Object)

One of the problems with the general lock implementation is that it is not exception-safe. Once an exception is thrown or the calling function throws an exception, it returns without releasing the lock. The result is a deadlock that can occur. This pattern is based on a destructor in C + +, which guarantees that a lock is acquired when the control flow enters scope, and the lock is released when the scope is left. The Mutex::autolock in Android and the Lock_guard in C + + belong to this category.

strategized Locking

The synchronization mechanism is parameterized through the strategy mode. Synchronization policies can be mutexes, rw/lock or semaphore, and so on. Can be implemented using polymorphic or template parameters. The former is suitable for runtime to know the strategy, the latter for the compile time.

Thread-safe Interface

The primary purpose of Thread-safe interface mode is to prevent self-deadlock of calls between components. Specifically, the object method is divided into interface layer and implementation layer. Interface layer functions are generally public, and they are responsible for obtaining release locks and synchronous checks, and then invoking the corresponding implementation layer functions. The implementation layer function assumes that the caller has obtained the appropriate lock and does not go up to the method that calls to the interface layer (otherwise it will deadlock). In many systems, a function followed by a locked or _l suffix represents the implementation layer function.

double-checked Locking (Lock Hint)

This pattern is used to reduce contention and synchronization overhead in critical section code that only needs to be executed once. For example, a critical section that needs to be executed once requires synchronization, and if a simple lock means that the lock will need to be checked every time, this is an additional overhead. Typically, for example, instance initialization in Singleton. The basic idea is to do two checks before entering the critical section, one at a time before locking, once in the lock. This way, when the second control flow arrives, the check before the lock is jumped, minus the cost of the lock. In POSIX, mutexes are basically implemented with Futex, which reduces the overhead of no-compete locks. But it is also widely used in performance-critical situations, such as kernel.

Concurrency Patterns Active Object (Concurrent object)

The Active object mode decouples function execution from function calls to simplify synchronization of shared state across different threads. The invocation of a function is made on the caller's thread, and the function executes on a separate threading, that is, the line Regulation regulation the scheduler thread of the active object. So function invocation and execution can be done in parallel. Proxy converts a function call to a call request, placed in the Scheduler activation list. Servant provides the implementation of this active object. For example, in a single-UI thread system, the UI control is an active object, and the other worker threads request the main thread to execute when they need to be modified.

Monitor Object (Thread-safe Passive object)

Monitor object guarantees that no matter how many threads are executed on this object, there is only one method of execution for each moment in the object. Both the Active object and monitor object modes can be used to schedule parallel execution of methods on the object. The difference is that the former is in a separate thread, the latter not. The advantage of the former is that some scheduling strategies can be implemented. The downside is the additional overhead of context switching and data movement. For example, many classes in Android that require parallel access have a mutex object that is first locked when the public interface is called.

Half-sync/half-async

Half-sync/half-async primarily decouples synchronous I/O operations from asynchronous I/O operations and adjusts the communication between the synchronization layer and the asynchronous layer by adding a queue layer. Specifically, for some time-consuming operations, you can simplify the parallel model by putting it in a separate thread in a synchronous fashion. For some short-time operations (Signal handler), calls are made asynchronously to improve performance. If they want to communicate with each other, the message is passed through the queue layer. Simply put, the lower layer gets the request and puts it into the queue, and the upper layer takes out the processing. Examples are asynctask in Android.

leader/followers

Multiple threads share a set of event sources in turn and detect, tap, distribute, and process service requests on these event sources. The core of the pattern is a thread pool. Specifically, only one thread (Leader) waits for a set of event sources at a time. Other threads (followers) are queued to become leader. When an event is detected, the leader line Chengcheng the worker thread, which completes the tap and distribution of the event. The event handler is eventually called. Multiple processing threads can work in parallel. When finished, the worker thread changes back to the follower thread, waiting to become the leader thread again. This pattern is used in both Scheduledthreadpoolexecutor and Delayqueue in Java.

thread-specific Storage

The thread-specific storage mode allows multiple threads to access global data on the "logic", but its physical objects are local. This will not cause synchronization overhead. Typically, the thread-specific storage access write proxy to encapsulate TLS. The use of this pattern is endless, such as the error code, or Android Looper, are placed in TLS.

"Pattern-oriented software Architecture, Patterns for Concurrent and networked Objects" Vol.2 notes

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.