JAVA concurrent much-thread basis (5)

The above describes the concurrent programming fences JAVA many concurrent threads base (4) . To help determine the thread through the finish line is the only one to perform more than one operation late next start.

LockSupport

It provides a relatively low-level thread pending operations. Somewhat similar suspend()method, but this method is not recommended.

  1. park()Make the current thread is suspended. Which is also called Unsafeclasses underlying operating.
public static void park() {
        UNSAFE.park(false, 0L);
    }
复制代码

2. unpark(Thread thread)is to continue down the current thread.

public static void unpark(Thread thread) {
        if (thread != null)
            UNSAFE.unpark(thread);
    }
复制代码

LockSupportUnlike the above two methods suspend()and resume()methods. In both methods resume()must be suspend()performed before. Otherwise the thread will be suspended forever, causing a deadlock. And LockSupportin the unparkcan parkbefore.

package com.montos.lock;
import java.util.concurrent.locks.LockSupport;

public class LockSupportDemo {
	public static Object obj = new Object();
	static ChangeObjectThread t1 = new ChangeObjectThread("t1");
	static ChangeObjectThread t2 = new ChangeObjectThread("t2");

	public static class ChangeObjectThread extends Thread {
		public ChangeObjectThread(String name) {
			super(name);
		}
		@Override
		public void run() {
			synchronized (obj) {
				System.out.println("in " + getName());
				LockSupport.park();
			}
		}
	}
	public static void main(String[] args) throws InterruptedException {
		t1.start();
		Thread.sleep(100);
		t2.start();
		LockSupport.unpark(t1);
		LockSupport.unpark(t2);
		t1.join();
		t2.join();
	}
}
复制代码

It can be seen through a small Demo above LockSupportmethod of use in the method of use is very simple. More space on concurrent classes in JDK were explained. Most used the CAS lock-free operations. Avoid thread blocking occurs.

Concurrent collections

In the daily business processes, we use the collection is one of the largest operations. That is, the corresponding three categories: Map, Setas well as the final List. In the case of a small amount of daily concurrent, so maybe we'll use the set corresponding to the operation:

//Map集合
private static final Map<String,String> map = Collections.synchronizedMap(new HashMap<String,String>());
//List集合	
private static final List<String> list = Collections.synchronizedList(new ArrayList<String>());
//Set集合
private static final Set<String> set = Collections.synchronizedSet(new HashSet<>());
复制代码

Above uses a Collectionssynchronization method for packaging. Inside depth understanding of the calling process, which is added on top of the various methods synchronizedlimit. The last thread-safe so as to achieve the purpose. If a large amount of concurrent, then it will affect the performance is, after all, it makes the corresponding read and write operations have become serial. So with several thread-safe following categories:

  • ConcurrentHashMapHigh-performance concurrent Map. Inside the action is with HashMapthe same. But there is more than a structure: Segment(segment).
static class Segment<K,V> extends ReentrantLock implements Serializable {
        private static final long serialVersionUID = 2249069246763182397L;
        final float loadFactor;
        Segment(float lf) { this.loadFactor = lf; }
    }
复制代码

It can be seen that he inherited the reentrant locks implementation. Why in this segment concept will be inside it? In order to better support high concurrent design of a concept. Each element in a particular section, the entire collection into a plurality of segments to manage, and high concurrent time, as long as the control of each segment can function as a synchronization.

And then count the number of times the size, ConcurrentHashMapthe use of the CounterCellstructure statistics. Each segment is stored in the size of this section, and then recycled summing the current situation of the array size.

final long sumCount() {
        CounterCell[] as = counterCells; CounterCell a;
        long sum = baseCount;
        if (as != null) {
            for (int i = 0; i < as.length; ++i) {
                if ((a = as[i]) != null)
                    sum += a.value;
            }
        }
        return sum;
    }
复制代码
  • BlockingQueueIt is a very good multi-threaded shared data container. When the queue is empty, the reader thread will wait, on the contrary, if the current queue is full, then write thread will wait. See the corresponding implementation class members will have the following three variables:
/** Main lock guarding all access */
final ReentrantLock lock; //加锁进行控制访问

/** Condition for waiting takes */
private final Condition notEmpty;//元素获取的时候,进行判断是否为空进行阻塞

/** Condition for waiting puts */
private final Condition notFull;//元素加入的时候,判断队列是否已满
复制代码

This above three variables to control access and increased element of the entire blocking queue. Fundamentally, he is not as described above ConcurrentHashMaphigh access performance, but what we need is the ability to multi-threaded access to his total data.

Elements blocking queue acquisition method

public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();//获取可中断锁
        try {
            while (count == 0)
                notEmpty.await();//队列为空,进行读线程等待
            return dequeue();
        } finally {
            lock.unlock();
        }
    }
复制代码
 private E dequeue() {
        // assert lock.getHoldCount() == 1;
        // assert items[takeIndex] != null;
        final Object[] items = this.items;
        @SuppressWarnings("unchecked")
        E x = (E) items[takeIndex];
        items[takeIndex] = null;
        if (++takeIndex == items.length)
            takeIndex = 0;
        count--;
        if (itrs != null)
            itrs.elementDequeued();
        notFull.signal();//通知写线程进行写入操作
        return x;
    }
复制代码

Blocking queue element method increases

public void put(E e) throws InterruptedException {
        checkNotNull(e);//判断元素是否为空
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();//获取可中断锁
        try {
            while (count == items.length)
                notFull.await();//队列满时,进行写线程等待
            enqueue(e);
        } finally {
            lock.unlock();
        }
    }
复制代码
private void enqueue(E x) {
        // assert lock.getHoldCount() == 1;
        // assert items[putIndex] == null;
        final Object[] items = this.items;
        items[putIndex] = x;
        if (++putIndex == items.length)
            putIndex = 0;
        count++;
        notEmpty.signal();//通知读线程进行操作 
    }
复制代码
  • ConcurrentLinkedQueueTurning to above is a multi-threaded shared data container, and this is the use of high concurrency. Inside a lot of use of lock-free operations and spin locks, can guarantee a good performance problems, there is little interest partners can get to know next.

Turning to above is complicated by the JDK on some simple introduction. After my introduction is complete, I will further explain the underlying source code, are interested can follow my little friends ~

Reproduced in: https: //juejin.im/post/5cf08d3c518825789e031472

Guess you like

Origin blog.csdn.net/weixin_34191845/article/details/91425038