Advanced Java Concurrency common interview questions summary

1.2. To talk about how he is using the synchronized keyword, it's used in the project

The main synchronized keyword used in three ways:

  • Modified Examples of the method:  apply to the current instance of the object locked , before entering the synchronization code to obtain the current lock object instance
  • Modified static method:: that is locked to the current class, will apply to all object instances of the class , because static members do not belong to any instance of an object, the class members (static indicates that this is a static resource class, regardless of the new how many objects, only one). So if a thread A non-static synchronized method calls an instance of an object, and the thread B needs to call this static synchronized method belongs to the class of the object instance, is allowed, mutual exclusion will not happen, because access static synchronized method lock is occupied the current class locks, access to non-static synchronized method lock is occupied by the current instance of the object lock.
  • Modified block:  designated lock object, to lock a given object, before entering the synchronization code library to obtain a given lock of the object.

Summary: synchronized static keyword added to a static method and synchronized (class) is the code block is locked to the class Class. Examples of the synchronized keyword added to the object instance is locked. Try not to use synchronized (String a) because the JVM, the string constant pool has a cache function!

Double check the lock object that implements the singleton (thread-safe)

 

public  class the Singleton { 

    Private  volatile  static the Singleton uniqueInstance; 

    Private the Singleton () { 
    } 

    public  static the Singleton GetUniqueInstance () {
        // first determine whether the object has too instance, has not been instantiated through before entering the code lock 
        IF (uniqueInstance == null ) {
             // class object locking 
            the synchronized (the Singleton. class ) {
                 IF (uniqueInstance == null ) { 
                    uniqueInstance = new new the Singleton (); 
                } 
            } 
        } 
        return uniqueInstance;
    }
}

 

 

① synchronized case statements sync blocks

achieve synchronized sync block of statements using the monitorenter and monitorexit instructions , wherein monitorenter instruction start position of the synchronization code points to blocks, monitorexit instruction indicating the end position of the synchronization code block. When performing monitorenter instruction thread tries to acquire a lock that is acquired monitor (monitor object exists in the subject header of each Java object, synchronized lock is acquired in this way locks, it is why any object in Java can be used as a lock reason) to their holding. When the counter is 0 can succeed, it will acquire the lock counter is set to 1 plus 1. After performing the appropriate monitorexit instruction, the lock counter is set to 0, indicating that the lock is released. If the lock fails to obtain the object that the current thread will block until another thread lock is released.

1.5. To talk about the difference between synchronized and ReentrantLock

① Both are reentrant lock

Both are reentrant lock. "Reentrant lock" concept is: they can get their own internal lock again. For example, a thread acquires the lock of an object, then the object lock has not been released, it again when you want to acquire a lock of this object can still get in, if not reentrant locks, it would cause a deadlock. Each time the same thread acquires the lock, the lock counters are incremented by one, so have to wait until the lock counter drops to zero in order to release the lock.

② synchronized depends on the JVM and ReentrantLock rely on API

synchronized is dependent on the JVM implementation, we also talked about in front of the virtual machine team a lot of optimization for the synchronized keyword in JDK1.6, but these optimizations are implemented in the virtual machine level, and not exposed directly to us. ReentrantLock JDK level is achieved (ie API level, we need to lock () and unlock () method with try / finally block to complete the sentence), so we can see its source code to see how it is implemented.

③ ReentrantLock than synchronized adds some advanced features

Compared synchronized, ReentrantLock added some advanced features. Mainly for the three main points: ① waiting can interrupt; ② can achieve a fair lock; ③ can achieve selective notification (lock can bind multiple conditions)

  • ReentrantLock provides a mechanism capable of interrupting the thread waiting for the lock, this mechanism is implemented by lock.lockInterruptibly (). That is awaiting threads can choose to give up waiting, changed other things.
  • ReentrantLock can specify whether fair or unfair lock lock. The only non-synchronized fair locks. The so-called fair lock is the first thread is waiting to acquire the lock. ReentrantLock non-default fair, you can ReentrantLock class ReentrantLock(boolean fair)to develop construction methods whether it is fair.
  • synchronized keyword and wait () and notify () / notifyAll () method may be implemented in conjunction with wait / notification mechanism, of course, also be realized class of ReentrantLock, but need the help Condition interface newCondition () method. Condition is only after JDK1.5, it has good flexibility, for example, can achieve multiple notification feature is to create multiple instances Condition (ie object monitors) in a Lock object, thread object can be registered in Condition specified, so that thread can be selectively notification, more flexibility in scheduling threads. When using a notification notify () / notifyAll () method, a thread is notified is selected by the JVM, the class with ReentrantLock Condition instance may be implemented in conjunction with "selective notice", this feature is very important, and the interface is available by default Condition . The synchronized keyword is equivalent to the entire Lock objects only a Condition instance, all threads are registered with it a body. If you do notifyAll () method will then inform all the threads in a wait state, it will cause great efficiency, while Condition instance signalAll () method will only be registered in the wake of the Condition instance all waiting threads.

2. volatile keyword

2.1. To talk about the Java Memory Model

Before JDK1.2, Java memory model implementation always from main memory (ie, shared memory) reading of variables, does not require any special attention. In the current Java memory model, a thread can be stored local memory variables such as machine registers ), rather than directly in the read and write main memory. This modification may result in a thread in the main memory of the value of a variable, while the other thread to continue using its copy of the variable's value in the register, resulting in inconsistent data.

 

 

To solve this problem, we need to declare a variable as volatile, which indicates the JVM, this variable is unstable, every time you use it will be read into main memory.

To put it plainly, the main role of the volatile keyword is to ensure the visibility of variables and then there is a role to prevent instruction reordering.

 

 

 

2.2. To talk about the difference between the synchronized keyword and volatile keywords

Compare the synchronized keyword and volatile keyword

  • The volatile keyword lightweight thread synchronization is achieved, the volatile performance is certainly better than the synchronized keyword. But the volatile keyword can only be used for variables can be modified method synchronized keyword and code blocks. Efficiency has been significantly improved after the synchronized keyword conducted mainly in order to reduce to obtain and release locks bring the performance overhead introduced by biased locking and lightweight locks and other various optimization after JavaSE1.6, the actual development use the keyword synchronized scenes or more.
  • Multithreaded access to the volatile keyword blocking will not occur, and may block the synchronized keyword occur
  • to ensure the visibility of the volatile keyword data, but can not guarantee the atomicity of data. Both the synchronized keyword can be guaranteed.
  • The volatile keyword is mainly used to solve the visibility of variables between multiple threads, and the synchronized keyword is solved resources between multiple threads to access synchronization.

3.1. ThreadLocal Profile

Under normal circumstances, we are creating a variable can be any one thread to access and modify. If you want to implement each thread has its own dedicated local variables how to solve it? JDK provided in ThreadLocalclass in order to solve this problem. ThreadLocalClass main solution is to allow each thread to bind their value can be ThreadLocala box like the image of the metaphor to store data, the box can store private data for each thread.

If you create a ThreadLocalvariable, then this variable access each thread will have a local copy of this variable, which is the ThreadLocalorigin of the name of the variable. They can be used  get() and the  set() method to get the default value or change the value to the value stored copy of the current thread, thereby avoiding the thread-safety issues.

3.3. ThreadLocal principle

From the  Threadstarting class source code.

public  class the Thread the implements Runnable { 
 ...... 
// ThreadLocal value associated with this thread. By the ThreadLocal class maintains 
ThreadLocal.ThreadLocalMap ThreadLocals = null ; 

// InheritableThreadLocal value associated with this thread. InheritableThreadLocal class maintains a 
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null ; 
 ...... 
}

 

From the above Threadclass source code can be seen that the Thread class has a  threadLocals and a  inheritableThreadLocals variable, they are  ThreadLocalMap the type of a variable, we can  ThreadLocalMap be understood as ThreadLocal customized class implements  HashMap. By default, these two variables are null, only the current thread calls  ThreadLocal the class  setor getcreate them only method actually calls these two methods, we call that ThreadLocalMapkind of correspondence  get(), set()method.

ThreadLocalClass set()method

 public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }
    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }

 

These contents of the above, we conclude that sufficient by guessing: The final variable is placed on the current thread  ThreadLocalMap in, there is not  ThreadLocal on, ThreadLocal can be understood as just ThreadLocalMapa package, passed variable values. ThrealLocal Class can Thread.currentThread()obtain the current thread object, the directly getMap(Thread t)you can access to the thread ThreadLocalMapobject.

Each Threadare provided with one ThreadLocalMap, and ThreadLocalMapmay be stored ThreadLocalas the key pairs. For example, we declare two in the same thread  ThreadLocal object, then, will use  Threadinternal use only are the ThreadLocalMap stored data, ThreadLocalMapthe key is to  ThreadLocaltarget, value is  ThreadLocal object calls setvalue method settings. ThreadLocal It is a map structure is to let each thread can be associated with multiple  ThreadLocalvariables. This also explains why the variables ThreadLocal declared its own dedicated local variables in each thread.

4.1. Why use a thread pool?

Thread pool provides a limit and manage resources (including the implementation of a task). Each thread pool also maintains some basic statistics, such as number of tasks have been completed.

Borrowing benefits about using a thread pool for "Java concurrent programming art" mentioned:

  • Reduce resource consumption. By reusing the thread has been created to reduce thread creation and destruction caused by consumption.
  • Improve the response speed. When the mission arrives, the task may not need to wait until the thread creation can be implemented immediately.
  • Thread improve manageability. A thread is a scarce resource, if the unlimited creation, not only consumes system resources, but also reduce the stability of the system, using a thread pool can be unified distribution, tuning and monitoring.

4.4. How to create a thread pool

Method one: ThreadPoolExecutor achieved constructor

package java_guide;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPoolTest {
    public static void main(String[] args) {
        BlockingQueue blockingQueue = new ArrayBlockingQueue(20);
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 15,
                60, TimeUnit.SECONDS, blockingQueue);
        for (int i = 0; i < 30; i++) {
            threadPoolExecutor.execute(new TaskWithoutResult(1000));
        }
        threadPoolExecutor.shutdown();
    }
}


class TaskWithoutResult implements Runnable {
    private int sleepTime = 1000;//默认睡眠时间1s

    public TaskWithoutResult(int sleepTime) {
        this.sleepTime = sleepTime;
    }

    @Override
    public void run() {
        System.out.println("Thread" + Thread.currentThread () + "start running" );
         the try { 
            the Thread.sleep (SleepTime); 
        } the catch (InterruptedException E) { // capture interrupt exception 

            System.out.println ( "thread" + Thread.currentThread () + "interrupted" ); 
        } 
        System.out.println ( "threads" + Thread.currentThread () + "end run" ); 
    } 
}
View Code

 

 

Second way: through tools Executors Executor framework to realize that we can create three types of ThreadPoolExecutor:

  • FixedThreadPool: This method returns a fixed number of threads in the thread pool. The number of threads in the thread pool is always the same. When there is a new task submission, if the thread pool idle threads is executed immediately. If not, the new task will be temporarily stored in a task queue, there is a thread to be idle, they handle tasks in the task queue.
  • SingleThreadExecutor: method returns only one thread of a thread pool. If more than one task is to submit to the thread pool, the task will be saved in a task queue until the thread is idle, to perform the task queue of first-in first-out order.
  • CachedThreadPool: This method returns a number of threads can be adjusted according to the actual thread pool. The number of threads in the thread pool is uncertain, but can be reused if idle threads will use the thread priority reusable. If all the threads are at work, another new task submission, new thread processing task is created. All threads in the current task is finished, it will return to the thread pool multiplex.

5.1. Atomic introduce atomic class

Atomic translated into Chinese is meant atoms. Chemically, we know that the minimum unit constituting atoms are generally substances in a chemical reaction are inseparable. We here at Atomic refers to one operation is not interrupted. Even when executed with multiple threads, an action once started, will not be interference from other threads.

The so-called Class Simple point is atoms having atomic type / operating characteristics atoms.

And contracting  java.util.concurrent atoms classes are stored in java.util.concurrent.atomicthe, as shown in FIG.

5.2. Atomic class JUC package in which four categories?

basic type

Using atomic update the basic types of

  • AtomicInteger: shaping atoms class
  • AtomicLong: Long-atomic
  • AtomicBoolean: Boolean - Atom

Array type

The use of atomic way to update an element of the array

  • AtomicIntegerArray: integer array atoms class
  • AtomicLongArray: Class atoms long integer array
  • AtomicReferenceArray: an array of reference type atom class

Reference types

  • AtomicReference: class reference type atom
  • AtomicStampedReference: update the reference type atom in the field of atomic-based
  • AtomicMarkableReference: update the reference type atom marked position

Object type attribute modification

  • AtomicIntegerFieldUpdater: atomic update field shaping updater
  • AtomicLongFieldUpdater: atomic update updater long integer field
  • 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 solution, ABA can solve problems that may arise when using CAS atomic updates.

Class common method AtomicInteger

 

public  Final  int GET () // Get the current value of the 
public  Final  int getAndSet ( int newValue) // Get the current value and set the new value of the 
public  Final  int getAndIncrement () // Get the current value and increment 
public  Final  int getAndDecrement () // get the current value and decrement 
public  Final  int getAndAdd ( int Delta) // get the current value and the expected value plus the 
Boolean of compareAndSet ( int expect, int Update) // if the value of the input equal to the expected value atomically set the value to the input value (Update)
public  Final  void lazySet ( int newValue) // final set newValue, after use lazySet settings may result in other threads within a short time after can still read the old value.

 

 

class AtomicIntegerTest {
         Private of AtomicInteger COUNT = new new of AtomicInteger ();
       // after use of AtomicInteger, this method does not require locking, thread safety can be achieved. 
        public  void INCREMENT () { 
                  count.incrementAndGet (); 
        } 

       public  int getCount () {
                 return count.get (); 
        } 
}

 

Guess you like

Origin www.cnblogs.com/ustc-anmin/p/11591904.html