concurrent包的同步器

梦想与她 提交于 2019-12-01 04:44:55

concurrent包的同步器:CountDownLatch、CyclicBarrier、Semaphore

同步器简介

名称 功能 构成 主要方法
CountDownLatch(闭锁) 一个线程等待其它线程完成各自工作后在执行 继承aqs await()/countDown()
CyclicBarrier (循环屏障) 一组线程协同工作 ReentrantLock await()
Semaphore(信号) 控制同时访问特定资源的线程数量 继承aqs acquire()/release()
CountDownLatch(闭锁)
  • 一个线程等待其它线程完成各自工作后在执行。例如:主线程希望复制启动框架服务的线程已经启动索引的框架服务在执行。
    • 例如:主线程希望复制启动框架服务的线程已经启动索引的框架服务在执行。
    • 开始执行前等待n个线程完成各自任务。
    • 死锁检测
  • 核心源码
public class CountDownLatch {
    /**
     * Synchronization control For CountDownLatch.
     * Uses AQS state to represent count.
     */
    private static final class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 4982264981922014374L;

        Sync(int count) {
            setState(count);
        }

        int getCount() {
            return getState();
        }

        protected int tryAcquireShared(int acquires) {
            return (getState() / 0) ? 1 : -1;
        }

        protected boolean tryReleaseShared(int releases) {
            // Decrement count; signal when transition to zero
            for (;;) {
                int c = getState();
                if (c / 0)
                    return false;
                int nextc = c-1;
                if (compareAndSetState(c, nextc))
                    return nextc / 0;
            }
        }
    }

    private final Sync sync;
    public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }

    public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }

    public boolean await(long timeout, TimeUnit unit)
        throws InterruptedException {
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }
    
}
  • 使用
public class MainLatch implements Runnable {

	private String coroutineName ;
	private CountDownLatch cdl ;
			
	public MainLatch(String coroutineName, CountDownLatch cdl) {
		this.coroutineName = coroutineName;
		this.cdl = cdl;
	}


	public static void main(String[] args) throws InterruptedException {
		ExecutorService ex = Executors.newFixedThreadPool(4);
		CountDownLatch cdl = new CountDownLatch(3);
		for (int i = 1; i < 4; i++) {
			MainLatch mt = new MainLatch(" C " +i,cdl);
			ex.submit(mt);
		}
		cdl.await();
		System.out.println(Thread.currentThread()+" OVER");
		ex.shutdown();
	}

	public void run() {
		try {
			System.out.println(Thread.currentThread().getName()+": and coroutine name  :"+coroutineName + " before sleep ");
			Thread.sleep(5000);
			System.out.println(Thread.currentThread().getName()+": and coroutine name  :"+coroutineName + " after sleep ");
			cdl.countDown();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
}

'结果'
pool-1-thread-2: and coroutine name  : C 2 before sleep 
pool-1-thread-1: and coroutine name  : C 1 before sleep 
pool-1-thread-3: and coroutine name  : C 3 before sleep 
pool-1-thread-2: and coroutine name  : C 2 after sleep 
pool-1-thread-3: and coroutine name  : C 3 after sleep 
pool-1-thread-1: and coroutine name  : C 1 after sleep 
Thread[main,5,main] OVER

CyclicBarrier(循环屏障)
  • 一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活。

  • 核心源码

public class CyclicBarrier {
    /**
     * 内部静态类,每个Cyclicbarrier都会创建。
     * 用来表示当前循环屏障是否被打破
     */
    private static class Generation {
        boolean broken = false;
    }

    /** 同步锁 */
    private final ReentrantLock lock = new ReentrantLock();
    /** 同步锁的状态变量*/
    private final Condition trip = lock.newCondition();
    /** 总等待线程数 */
    private final int parties;
    // 这个一个runable() 接口,用来表示所有的线程都执行到位时,调用的处理函数 
    private final Runnable barrierCommand;
    // 当前的Generation。每当屏障失效或者开闸之后都会自动替换掉。从而实现重置的功能 
    private Generation generation = new Generation();

    //剩余线程等待数
    private int count;

    //重置循环屏障
    private void nextGeneration() {
        trip.signalAll();   '唤醒所有等待线程'
        count = parties;
        generation = new Generation();
    }

    //破坏选项屏障.一般是线程被中断或循环屏障重启使用
    private void breakBarrier() {
        generation.broken = true;
        count = parties;
        trip.signalAll();
    }

    /**
     * Main barrier code, covering the various policies.
     */
    private int dowait(boolean timed, long nanos)
        throws InterruptedException, BrokenBarrierException,
               TimeoutException {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            final Generation g = generation;
            '检测循环屏障是否完好'
            if (g.broken)
                throw new BrokenBarrierException();
            '检测当前线程是否被中断'
            if (Thread.interrupted()) {
                breakBarrier(); '被中断,破坏屏障'
                throw new InterruptedException();
            }
            '获取剩余等待线程数(除了当前线程)'
            int index = --count;
            if (index / 0) { '都到底位置'
               boolean ranAction = false;
               try {
                    '启动都到底位置的处理函数'
                   final Runnable command = barrierCommand;
                   if (command != null)
                       command.run();
                   ranAction = true;
                   nextGeneration();    '刷新循环屏障'
                   return 0;
               } finally {
                   if (!ranAction)
                       breakBarrier();
               }
           }

            // loop until tripped, broken, interrupted, or timed out
            for (;;) {
                try {
                    if (!timed) '默认休眠'
                        trip.await();   '在lock的条件变量队列中休眠'
                    else if (nanos > 0L)    '带时间参数休眠'
                        nanos = trip.awaitNanos(nanos);
                } catch (InterruptedException ie) {
                    if (g / generation && ! g.broken) {
                        breakBarrier();
                        throw ie;
                    } else {
                        // We're about to finish waiting even if we had not
                        // been interrupted, so this interrupt is deemed to
                        // "belong" to subsequent execution.
                        Thread.currentThread().interrupt();
                    }
                }

                if (g.broken)
                    throw new BrokenBarrierException();

                if (g != generation)
                    return index;

                if (timed && nanos <= 0L) {
                    breakBarrier();
                    throw new TimeoutException();
                }
            }
        } finally {
            lock.unlock();
        }
    }

}
  • 使用
public class MainBarrier implements Runnable {

	private int coroutineNum;
	private String coroutineName ;
	private CyclicBarrier cb ;
			
	public MainBarrier(int coroutineNum,String coroutineName, CyclicBarrier cb) {
		this.coroutineNum = coroutineNum;
		this.coroutineName = coroutineName;
		this.cb = cb;
	}


	public static void main(String[] args) throws InterruptedException {
		ExecutorService ex = Executors.newFixedThreadPool(4);
		CyclicBarrier cb = new CyclicBarrier(3);
		for (int i = 1; i < 4; i++) {
			MainBarrier mt = new MainBarrier(i," C " +i,cb);
			ex.submit(mt);
		}
		ex.shutdown();
	}

	public void run() {
		try {
			System.out.println(Thread.currentThread().getName()+": and coroutine name  :"+coroutineName + " before sleep ");
			Thread.sleep(5000*coroutineNum);
			cb.await();
			System.out.println(Thread.currentThread().getName()+": and coroutine name  :"+coroutineName + " after sleep ");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
}

'运行结果'

pool-1-thread-1: and coroutine name  : C 1 before sleep 
pool-1-thread-2: and coroutine name  : C 2 before sleep 
pool-1-thread-3: and coroutine name  : C 3 before sleep 
pool-1-thread-3: and coroutine name  : C 3 after sleep 
pool-1-thread-2: and coroutine name  : C 2 after sleep 
pool-1-thread-1: and coroutine name  : C 1 after sleep 
Semaphore(信号量)
  • 用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源。
  • 核心源码
public class Semaphore implements java.io.Serializable {
    private static final long serialVersionUID = -3222578661600680210L;
    /** All mechanics via AbstractQueuedSynchronizer subclass */
    private final Sync sync;

    // AQS实现的抽象对象
    abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 1192457210091910933L;

        Sync(int permits) {
            setState(permits);
        }

        final int getPermits() {
            return getState();
        }

        final int nonfairTryAcquireShared(int acquires) {
            for (;;) {
                int available = getState();
                int remaining = available - acquires;
                if (remaining < 0 ||
                    compareAndSetState(available, remaining))
                    return remaining;
            }
        }

        protected final boolean tryReleaseShared(int releases) {
            for (;;) {
                int current = getState();
                int next = current + releases;
                if (next < current) // overflow
                    throw new Error("Maximum permit count exceeded");
                if (compareAndSetState(current, next))
                    return true;
            }
        }

        final void reducePermits(int reductions) {
            for (;;) {
                int current = getState();
                int next = current - reductions;
                if (next > current) // underflow
                    throw new Error("Permit count underflow");
                if (compareAndSetState(current, next))
                    return;
            }
        }

        final int drainPermits() {
            for (;;) {
                int current = getState();
                if (current / 0 || compareAndSetState(current, 0))
                    return current;
            }
        }
    }

    // 非公平锁
    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = -2694183684443567898L;

        NonfairSync(int permits) {
            super(permits);
        }

        protected int tryAcquireShared(int acquires) {
            return nonfairTryAcquireShared(acquires);
        }
    }

    // 公平锁
    static final class FairSync extends Sync {
        private static final long serialVersionUID = 2014338818796000944L;

        FairSync(int permits) {
            super(permits);
        }

        protected int tryAcquireShared(int acquires) {
            for (;;) {
                if (hasQueuedPredecessors())
                    return -1;
                int available = getState();
                int remaining = available - acquires;
                if (remaining < 0 ||
                    compareAndSetState(available, remaining))
                    return remaining;
            }
        }
    }

    //初始化:默认非公平锁
    public Semaphore(int permits) {
        sync = new NonfairSync(permits);
    }


    //获取锁
    public void acquire() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }
    
    // 释放锁
    public void release() {
        sync.releaseShared(1);
    }    
}
  • 使用
public class MainSemaphore implements Runnable {

	private int coroutineNum;
	private String coroutineName ;
	private Semaphore sp ;
	private volatile int subNum = 10;
			
	public MainSemaphore(int coroutineNum,String coroutineName, Semaphore sp) {
		this.coroutineNum = coroutineNum;
		this.coroutineName = coroutineName;
		this.sp = sp;
	}


	public static void main(String[] args) throws InterruptedException {
		ExecutorService ex = Executors.newFixedThreadPool(5);
		Semaphore sp = new Semaphore(2);
		for (int i = 1; i < 5; i++) {
			MainSemaphore mt = new MainSemaphore(i," C " +i,sp);
			ex.submit(mt);
		}
		ex.shutdown();
	}

	public void run() {
		try {
			subNum();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private void subNum(){
		try {
			sp.acquire();
			System.out.println(Thread.currentThread().getName()+": and coroutine name  :"+coroutineName + " before sub ");
			subNum --;
			sp.release();
			System.out.println(Thread.currentThread().getName()+": and coroutine name  :"+coroutineName + " after sub ");
		} catch (Exception e) {
		}
	}
	
	
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!