展开
拓展 关闭
订阅号推广码
GitHub
视频
公告栏 关闭

Semaphore使用及源码分析

  • 简介
控制并发数量
使用场景:接口限流
  • 案例1
import java.util.concurrent.Semaphore;

public class SemaphoreDemo {

    public static void main(String[] args) {
        // 指定个数
        Semaphore semaphore = new Semaphore(8);

        // 创建10个线程
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                try {
                    semaphore.acquire();            // 获得信号后才能执行
                    System.out.println(Thread.currentThread().getName() + "开始执行");
                    Thread.sleep(5000L);        // 模拟该线程要执行复杂的操作
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    semaphore.release();            // 释放信号
                }
            }).start();
        }
    }
    
}

# 控制台打印结果:最后线程8和线程9要过一会儿才打印,这是因为这2个线程被限制了,要等其他线程释放信号,才开始执行
Thread-0开始执行
Thread-6开始执行
Thread-2开始执行
Thread-7开始执行
Thread-5开始执行
Thread-4开始执行
Thread-1开始执行
Thread-3开始执行
Thread-9开始执行
Thread-8开始执行

Process finished with exit code 0
  • 源码分析
# 查看Semaphore类
    public Semaphore(int permits) {
        sync = new NonfairSync(permits);      // 当我们执行信号量个数时,其实是new 的非公平实现
    }

# 查看NonfairSync方法
    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = -2694183684443567898L;

        NonfairSync(int permits) {
            super(permits);        // 调用super方法
        }

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

# 查看super方法
    abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 1192457210091910933L;

        Sync(int permits) {
            setState(permits);      // 设置状态,上面传入的参数是8,则这里的状态是8
        }

        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;
            }
        }

# 查看acquire方法
    public void acquire() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }

# 查看acquireSharedInterruptibly方法
    public final void acquireSharedInterruptibly(int arg)
            throws InterruptedException {
        if (Thread.interrupted())          // 线程中断时,抛出异常
            throw new InterruptedException();
        if (tryAcquireShared(arg) < 0)        // 执行tryAcquireShared方法
            doAcquireSharedInterruptibly(arg);
    }

# 查看tryAcquireShared方法
    protected int tryAcquireShared(int arg) {
        throw new UnsupportedOperationException();
    }

# 查看实现类

    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;  // 总个数 - 1,acquires表示每次传入的1
                if (remaining < 0 ||
                    compareAndSetState(available, remaining))      // 判断是否小于0,返回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;
            }
        }
    }

# 查看release方法
    public void release() {
        sync.releaseShared(1);
    }

# 查看releaseShared
    public final boolean releaseShared(int arg) {
        if (tryReleaseShared(arg)) {
            doReleaseShared();
            return true;
        }
        return false;
    }

# 查看tryReleaseShared方法
    protected boolean tryReleaseShared(int arg) {
        throw new UnsupportedOperationException();
    }

# 查看实现 

        protected final boolean tryReleaseShared(int releases) {
            for (;;) {
                int current = getState();      // 获取状态,即是总个数
                int next = current + releases;    // 当前总个数 + 每次releases的值,每次releases的值为1;相当于他已经释放了,其他线程可以去获取
                if (next < current) // overflow      // 如果结果数小于之前总个数,抛出异常
                    throw new Error("Maximum permit count exceeded");
                if (compareAndSetState(current, next))
                    return true;
            }
        }
posted @ 2022-05-16 11:53  DogLeftover  阅读(22)  评论(0编辑  收藏  举报