Java concurrent programming (4) Common synchronization tools

Source: Internet
Author: User

Java concurrent programming (4) Common synchronization tools

The synchronization tool class can enable any type of object, as long as the object can coordinate and control the control flow of the thread according to its own State. Blocking queues can be used as synchronization tools. Other types of synchronization tools also include:Semaphores(Semaphore ),Barrier(Barrier)And locking(Latch ).


Locking

First, we will introduce locking.

Locking is equivalent to a door: before locking to a certain state, the door is always closed, and all threads will wait (blocking) in front of the door ). Only when the door is opened will all threads continue to run at the same time.

Blocking can be used to ensure that certain activities are not executed until other activities are completed. For example:

1. Make sure that a computing task is executed after all its resources are initialized. Binary locks (only two States) can be used to indicate that "resource R has been initialized", and all R operations must wait for this lock first.

2. Make sure that a service is started only after all other services are started. Multiple locks are required. Let S wait for each lock. the operation will continue only after all locks are enabled.

3. Wait until the participants (for example, players in multi-player games) of an operation are ready to continue. In this case, when all players are ready, the lock will end.

CountDownLatch is a flexible locking implementation that can be used in the above situations. The lock status contains a counter, initialized to a positive number, indicating the number of events to wait. The countDown () method will decrease the counter, indicating that one of the waiting events has occurred. The await () method is blocked until the counter value changes to 0.

Next, we use locks to implement the function of calculating the running time of multiple sub-threads in the main thread. The specific logic is to use two locks. The "start gate" is used to control the sub-thread running at the same time, and the "End Gate" is used to identify whether the Sub-thread ends.

Package org. bupt. xiaoye; import java. util. concurrent. countDownLatch; public class Test {public static int nThread = 5; public static void main (String [] args) throws InterruptedException {final CountDownLatch startGate = new CountDownLatch (1 ); final CountDownLatch endGate = new CountDownLatch (nThread); for (int I = 0; I
 
  

FutureTask

FutureTask can also be used as a lock. It indicates an abstract computation that can generate results. It is implemented through Callable, which is equivalent to a Runnable that can generate results and can be in the following three States: Waiting for running, running, and running completed. When FutureTask enters the completion state, it will stay in this state.

Future. get is used to obtain the calculation result. If FutureTask is not completed yet, it will be blocked. FutureTask transmits the computing result from the execution thread to the thread that obtains the result. The FutureTask specification ensures the safe release of the result in this transfer process.

FutureTask indicates an asynchronous task in the Executor framework. It can also be used to represent some long computations that can be started before the calculation results are used.

Next we will construct a simple asynchronous task to demonstrate how to use FutureTask.

package org.bupt.xiaoye;import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util.concurrent.FutureTask;public class Preloader {private final FutureTask
   
     future = new FutureTask
    
     (new Callable
     
      () {public Integer call() throws Exception {Thread.sleep(3000);return 969;}});private final Thread thread = new Thread(future);public void start() {thread.start();}public Integer get() throws Exception {try{return future.get();}catch(ExecutionException e){Throwable cause = e.getCause();throw launderThrowable(cause);}}private static Exception launderThrowable(Throwable cause) {if(cause instanceof RuntimeException)return (RuntimeException )cause;else if(cause instanceof Error) throw (Error) cause;else throw new IllegalStateException("Not Checked",cause);}public static void main(String[] args) throws Exception{Preloader p = new Preloader();p.start();long start = System.currentTimeMillis();System.out.println(p.get());System.out.println(System.currentTimeMillis()-start);}}
     
    
   

Semaphores

Previously, locking controls the access time, while semaphores are used to control the number of operations to access a specific resource and control the space. Moreover, locking can only be reduced and used at one time, while semaphores can be applied for release and can be increased or decreased. A counting semaphore can also be used to implement a certain resource pool or impose a boundary on the container.

Semaphone manages this set of licenses (permit), which can be specified by constructors. The blocking method acquire is also provided to obtain the license. The release method is provided to release a license.

Semaphone can change any container to a bounded blocking container, for example, used to implement a resource pool. For example, the database connection pool. We can construct a fixed-length connection pool and use the blocking methods acquire and release to obtain and release the connection, instead of failing to get the connection. (Of course, it is easier to use BlockingQueue to save resources in the connection pool at the beginning of the design)

For example, we can change a common set container to a blocking bounded container.

package org.bupt.xiaoye;import java.util.Collections;import java.util.HashSet;import java.util.Set;import java.util.concurrent.Semaphore;public class BoundedHashSet
   
     {private final Set
    
      set;private Semaphore sem;public BoundedHashSet(int bound) {if (bound < 1)throw new IllegalStateException();set = Collections.synchronizedSet(new HashSet
     
      ());sem = new Semaphore(bound);}public boolean add(T e) throws InterruptedException {sem.acquire();boolean wasAdded = false;try {wasAdded = set.add(e);return wasAdded;} finally {if (!wasAdded)sem.release();}}public boolean remove(T e) {boolean wasRemoved = set.remove(e);if (wasRemoved)sem.release();return wasRemoved;}}
     
    
   


Barrier

Bariier is similar to blocking, which can block a group of threads to know that an event occurs. The key difference between a barrier and a lock is that all threads must reach the barrier position at the same time to continue execution. Blocking is used to wait for the wait time, while the fence is used to wait for the thread.

CyclicBarrier can aggregate a certain number of participants at the barrier position repeatedly. It is very useful in parallel Iteration Algorithms: splitting a problem into a series of independent subproblems. When a thread reaches the barrier position, call the await () method. This method is to block the method until all threads reach the barrier position. Then, the barrier is opened and all threads are released, the fence will be reset for next use.

Another form of fence is the Exchanger, which is a Two-Party fence where all parties exchange data. For example, when a thread wants to write data in the buffer zone, another thread reads data from the buffer zone. These threads can use Exchanger to converge and exchange slow buffers with empty buffers. When two threads exchange objects through Exchanger, this exchange securely releases these two objects to the other.

Exchanger may be considered as a bidirectional form of SynchronousQueue. We can also use two SynchronousQueue to implement the Exchanger function.

class FillAndEmpty {   Exchanger
   
     exchanger = new Exchanger
    
     ();   DataBuffer initialEmptyBuffer = ... a made-up type   DataBuffer initialFullBuffer = ...   class FillingLoop implements Runnable {     public void run() {       DataBuffer currentBuffer = initialEmptyBuffer;       try {         while (currentBuffer != null) {           addToBuffer(currentBuffer);           if (currentBuffer.isFull())             currentBuffer = exchanger.exchange(currentBuffer);         }       } catch (InterruptedException ex) { ... handle ... }     }   }   class EmptyingLoop implements Runnable {     public void run() {       DataBuffer currentBuffer = initialFullBuffer;       try {         while (currentBuffer != null) {           takeFromBuffer(currentBuffer);           if (currentBuffer.isEmpty())             currentBuffer = exchanger.exchange(currentBuffer);         }       } catch (InterruptedException ex) { ... handle ...}     }   }   void start() {     new Thread(new FillingLoop()).start();     new Thread(new EmptyingLoop()).start();   }  }
    
   




Related Article

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.