"Concurrent Programming in the Java art" Chapter 6,7 Java concurrent containers and the frame / Java 13 atomic operation

Chapter 6 Java concurrent containers and frameworks

6.1 ConcurrentHashMap (thread-safe HashMap, lock segmentation technology)

6.1.1 Why do you want to use ConcurrentHashMap

  Use HashMap in concurrent programming could lead to program loops, and thread-safe HashTable efficiency and very low . For these two reasons, there was the debut of ConcurrentHashMap opportunity.

  (1) thread-safe HashMap

  In a multithreaded environment, for use HashMap put operation may cause an infinite loop (as will lead to multi-thread chain HashMap forms an annular Entry data structure, the next node Entry never empty, will produce an endless loop Get Entry.), Resulting in close to 100% CPU utilization, can not be used in the HashMap concurrency.

  (2) inefficient HashTable

  HashTable containers sychronized to ensure thread safety, but HashTable in the fierce competition in the thread very inefficient. Because when a thread synchronization method of access HashTable, when other threads have access HashTable synchronization method, and enters the blocking or polling state. Such as thread element to be put to use 1, thread 2 will not be able to add elements, can not use the get method to get the elements using put method, so the lower the efficiency of more intense competition.

  (3) ConcurrentHashMap the lock segmentation technique can effectively enhance the rate of concurrent access

  The reason HashTable container in a highly competitive environment concurrent low performance efficiency is all access HashTable threads must compete for the same lock. If the container how to lock, each lock for locking the container in which part of the data, so when multiple threads access different data container segments, inter-thread lock contention would not exist, which can effectively improve the efficiency of concurrent access this is used ConcurrentHashMap lock segmentation techniques . First, the data is divided into a section of the store, and then give every piece of data with a lock, a thread holding the lock when accessing data in which some of the other segment of data can also be accessed by other threads .

ConcurrentHashMap structure:

  ConcurrentHashMap by the Segment array structure and HashEntry array of structures composed. Segment is reentrant lock, the lock role; HashEntry storing key data .
  A ConcurrentHashMap contains a Segment array, similar to the structure of Segment and HashMap, a list structure and the array. HashEntry a Segment contains an array, each element of a list is HashEntry structure, each of a guardian HashEntry Segment array elements. When the data HashEntry modify array, it must first obtain the corresponding Segment lock .

 

ConcurrentHashMap operations:

  get operation : get locking process does not require , a null value only when it is re-read lock . (How do unlocked? GET method to be used in shared variables are defined as volatile type .)

  put operation : put the process must be locked (due to the need to put methods in the shared variable write operation, so in order to thread safety, must be locked in operation shared variables) . The method put first positioned Segment, and then insert operation in the segment .

  Insert Procedure: The first step in determining whether it is necessary Segment HashEntry array of expansion, the second step the position of the positioning element is added, and then place HashEntry array.

  • The need for expansion? Before determining whether to insert elements in the Segment HashEntry exceeds the capacity of the array (threadshold), exceeds the threshold value, the expansion of the array.
  • How to expansion? At the time of expansion, first creates a capacity of twice the original capacity of the array, then elements in the original array after re-hash inserted into a new array. For efficient, ConcurrentHashMap not for expansion of the entire vessel, but only for a certain segment for expansion.

size operation : first try two times to count each Segment size by way of Segment not locked, if the statistical process count has changed, then again by way of an unlocked (when all the statistical size of Segment put, remove, clean All lock method) to count the size of all of the Segment.

  • How to determine whether ConcurrentHashMap in the statistics when the vessel has changed it? Use modCount variable, the variable modCount front element will be added to 1, then compare modCount whether changes in size before and after statistics put, remove and clean method in operation, so that the size of the vessel has changed.

6.2 ConcurrentLinkedQueue (non-blocking thread-safe queue)

  Implement a thread-safe queue in two ways:

  • Use blocking method: implemented with a lock (enqueue and dequeue with the same lock) or with the two locks (enqueue and dequeue with different locks) or the like.
  • Nonblocking method: using a loop CAS.

  ConcurrentLinkedQueue is unbounded thread-safe queue based on linked nodes, the "FIFO" rule sorting nodes. It uses a "wait-free" algorithm (algorithm i.e. CAS) is achieved.

6.3 blocking queue

  Blocking queue (BlockingQueue) is a support for two additional operations queue. These two additional operational support insertion and removal method of blockage .

  • Supports blocking insertion method: When the queue is full, the queue will block the thread insert elements until the queue dissatisfaction.
  • Supports blocking removal method: When the queue is empty when retrieving an element of thread waits for the queue to become non-empty.

  Blocking queue commonly used in producer and consumer scenarios: the producer thread element is added to the queue, the consumer is the thread to take elements from the queue. Blocking queue is used to store elements producers, consumers used to get the container element .

 

  In the non-blocking queue seasonal, two additional operations (insertion and removal) of four kinds of treatment:

The method / approach Throw an exception Returns the special value Has been blocked Timeout exit
Insertion method add(e) offer(e) put(e) offer(e, time, unit)
Removal Method remove() poll() take() poll(time, unit)
Inspection Method element() peek() unavailable unavailable
  • Throws an exception: When the queue is full, if you go down to the queue insert element throws IllegalStateException ( "Queue full") exception. When the queue is empty when retrieving an element from the queue NoSuchElementException will throw an exception.
  • Returns the special value: When an element is inserted into the queue, returns the element is inserted success, returns true if successful. If the method is to remove, removed from a queue element, if there is no null is returned.
  • It has been blocked: When blocking queue is full, if the producer thread to put queue element, the queue will block until the producer thread until the queue is available or respond to abort. When the queue is empty, if consumers threaded column take elements from the queue, the queue consumer thread will be blocked until the queue is not empty.
  • Exit Timeout: When the blocking queue is full, if the producer thread insert elements into the queue, the queue will block the producer thread for some time, if the timeout exit.

[Note: If you are unbounded blocking queue, the queue will be full of impossible situations, the use of put or offer methods will never be blocked, but also offer the use of the method, the method returns true forever.

JDK7 offers seven blocked queue:

  • ArrayBlockingQueue: an array of structures bounded blocking queue , according to the FIFO principle elements to sort.
  • LinkedBlockingQueue: linked list of structures bounded blocking queue , default and maximum length is Integer.MAX_VALUE, according to FIFO principle elements to sort.
  • PriorityBlockingQueue: Support unbounded blocking priority queue default natural elements taken in ascending order. We do not guarantee the same priority order of the elements .
  • DelayQueue: Support delay elements acquired unbounded blocking queue . PriorityQueue achieved using queue, the queue of Delayed elements must implement the interface, you can specify when you create an element how long it takes to get the current element from the queue. Only elements can be extracted from the queue when the delay has expired. It can be used:
    • Design caching system: save with DelayQueue cache element of validity, using a thread loop query DelayQueue, once DelayQueue acquired elements from the cache lifetime to represent.
    • Timing task scheduling: tasks and execution time DelayQueue saved the day will be executed once DelayQueue get from the start to the task execution, such as TimerQueue is to use DelayQueue implemented.
  • SynchronousQueue: blocking queue does not store elements . Put each operation must wait for a take, otherwise can not continue to add elements.
  • LinkedTransferQueue: linked list structure consisting of unbounded blocking queue TransferQueue . Compared to other blocking queue, LinkedTransferQueue more tryTransfer and transfer methods.
    • transfer: If consumers are currently waiting to receive the element, transfer method can producers element passed immediately passed to consumers. If there are no consumers are waiting to receive the element, the element will be stored in a queue and wait until the tail node of calcium consumed by consumers before returning.
    • tryTransfer: If the consumer is not waiting to receive the element, then immediately returns false.
  • LinkedBlockingDeque: two-way linked list structure consisting of blocking queue . Elements can be inserted and removed from both ends of the queue.

The principle of blocking queue:

  If the queue is empty, consumers will have to wait, when producers add elements, how consumers know the current queue has elements of it?

  Using the notification mode to achieve . When a producer is to fill the queue will block live Producer elements are added, when consumer spending elements of a queue, the queue will inform producers currently available.

6.4 Fork / Join framework

  • Fork / Join framework is a framework for performing a task in parallel , a large tasks divided into several small task, to obtain a large frame final summary results of the task results after each small task .
  • Work-stealing algorithm : is a thread steal from other pull queue tasks to perform. If we need to do a large task, we can put this task into a number of non-dependent sub-tasks, in order to reduce competition among threads, so these subtasks are placed in different queue and for each queue create a separate thread to perform the task queue, the queue threads and correspondence, such as a thread is responsible for handling a queue of tasks. But some thread will put its own task queue finish, while the other threads as well as the corresponding task queue waiting to be processed. The work was done instead of waiting threads, it is better to help other thread work, then it will go to other threads queue steal a task to perform. And at this time they access the same queue, so in order to reduce theft and stolen the task thread competition between the task threads, often using double-ended queue, the task thread never get stolen from the head deque task execution, the theft task thread never take the task execution from the end of double-ended queue.
    • Advantages work-stealing algorithm is thread take advantage of parallel computing, and reduce competition between threads, which is a disadvantage in some cases there is still competition, such as the two ends of only one task queue. And consume more system resources, such as creating multiple threads and multiple double-ended queue.

Fork / Join framework of design :

  Step 1: segmentation tasks . First class needs a fork to the big task into subtasks, there may be sub-task is still very large, so it needs to keep dividing until the divided sub-tasks small enough.

  Step 2: Perform tasks and merging the results . Subtasks are divided on the double-ended queue, then start several threads are acquired from the double-ended task execution queue. The results of executing the subtasks are united in a queue, start a thread to get data from the queue, and then merge the data.

  Fork / Join using two or more classes to perform two things:

  • ForkJoinTask : we want to use ForkJoin frame, you must first create a ForkJoin task. It provides a fork in the task () and join () operation mechanism, usually we do not need the direct successor to ForkJoinTask class, but only need to inherit its subclasses, Fork / Join framework provides the following two sub-categories:
    • RecursiveAction: did not return for the results of the task.
    • RecursiveTask: There used to return the results of the task.
  • ForkJoinPool : ForkJoinTask need to be performed by ForkJoinPool.
    • ForkJoinPool by the ForkJoinTask and ForkJoinWorkerThread array of arrays, array ForkJoinTask responsible for storing the program will be submitted to the ForkJoinPool task, and ForkJoinWorkerThread array responsible for carrying out these tasks.

  Task into a sub-task is added to the current worker threads maintained double-ended queue, into the head of the queue. When a worker thread queue currently have no job, it will randomly get a task from the other end of the queue worker threads.

Fork / Join framework of exception handling :

  ForkJoinTask in the course of implementation may throw an exception, but we can not directly catch the exception in the main thread, so ForkJoinTask provides isCompletedAbnormally () method to check whether the task has been thrown or had been canceled, and through the ForkJoinTask getException method to get an exception. Which, getException method returns a Throwable object, if the task was canceled CancellationException is returned if the task is not complete or is not thrown null is returned.

Chapter 7 Java atomic operations in class 13

  When the program updates a variable, if multiple threads simultaneously update this variable might get value beyond expectations. Usually we use sychronized to solve this problem, sychronized will ensure that multiple threads do not simultaneously update the same variable.

  Java JDK1.5 from the beginning provided java.util.concurrent.atomic package, package type atomic operation is provided a use of simple, efficient performance, updating a variable thread safe manner. Provided a total of 13 classes, four types of atoms belonging to the update method, the basic types are the atomic update, update the array atom, atoms and atomic updates update the reference attributes (fields).

(1) Basic type atomic update

  • AtomicBoolean: atomic update Boolean
  • AtomicInteger: integer atomic updates
  • AtomicLong: atomic update Long

(2) update the array atoms

  • AtomicIntegerArray: atomic update integer array of elements
  • AtomicLongArray: atomic update long integer array of elements
  • AtomicReferenceArray: atomic update the reference array element type

(3) update the reference type atom

  • AtomicReference: atomic update reference type
  • AtomicReferenceFieldUpdater: atomic update reference types in the field
  • AtomicMarkableReference: update the reference type atom marked position. Atom may update a boolean flag and the type of application

(4) Update Field atoms class

  • AtomicIntegerFieldUpdater: integer atomic update field updater
  • AtomicLongFieldUpdater: atomic update of long integer field updater
  • AtomicStampedReference: atomic update version number with a reference type. Such references are associated with the integer value it can be used to update data and the version number of atoms, can solve the problems that may occur when ABA using CAS atomic updates.

[Note] To update atomically field class requires two steps. The first step: Because atomic update field class is an abstract class, must be used every time you use the static method newUpdate () to create an updater, and the need to set up classes and attributes you want to update. Step two: Update class field (property) must use public volatile modifier.

 

Guess you like

Origin www.cnblogs.com/toria/p/bingfa67.html