美文网首页Java-多线程
Semaphore 多线程并发控制

Semaphore 多线程并发控制

作者: PageThinker | 来源:发表于2020-04-14 17:42 被阅读0次
    1.png

    01 Semaphore

    Semaphore 的作用就是控制某段程序线程并发执行的数量。这比 sychronized 功能更加强大和方便。

    Semaphore 有个一个参数为 permits 的构造函数。(permist 指的是同一时间内允许多少个线程同时执行 acquire()和 release()之间的代码。

    ...
    private final Semaphore semaphore = new Semaphore(1);
    ...
    public void work() {
        ...
        semaphore.acquire();
        ...
        semaphore.relose();
        ...
    }
    

    Semaphore 只能控制共用一个 Semaphore 对象的线程时间的同步。 不同 semaphore 之间的线程时无法控制的。

    02 Semaphore 中的常用方法

    构造函数参数 permits,通过构造参数指定许可证数量。

    acquire(): 使用构造函数中的 permits 中的值,限制线程执行 acquire和release 之间的线程数。

    acquire(int permits) 每执行一次从 初始化的 permits 申请 x 个认证数,申请了 x 个必须 release x 个证书才能继续向下执行。

    acquireUninterruptibly() 使进入 acquire()方法线程,不允许被中断。

    availablePermits() 返回当前可用的许可数。

    drainPermits() 返回当前可用的许可数,并将许可数设置为 0

    getQueueLength() 取得等待许可的线程数

    hasQueueLength() 判断有没有线程在等待这个许可。

    tryAcquire() 尝试获取一个许可,若获取不到则返回 false,此方法通常与 if 结合,具有无阻塞的特点(即不需要在等待处一直等待),若 if 不成立则直接返回 else 语句。

    tryAcquire(int permits) 尝试获取 permits 个许可,若获取不到则返回 false

    tryAcquire(long timeout, TimeUnit unit) 在制定的实现内获取 1 个许可

    tryAcquire(int permits, long timeout, TimeUnit unit) 尝试在指定的时间内获取 permits 个许可。

    2.png

    03 公平和非公平信号量

    公平信号量:获得锁的顺序与线程执行的顺序有关。

    非公平信号量:获得锁的顺序与线程执行的顺序无关。

    04 扩展

    (1)线程和 CPU 之间的关系。

    线程过多会导致 CPU 资源被耗尽,每个线程执行过程都相当缓慢,因为 CPU 除了把时间片段分配给了不同的线程,在切换不同上下文时也是需要时间的,因此线程数过多会导致系统性能大幅降低。

    (2)多线程同步

    多线程同步指的是排队执行某一任务,执行的任务是一个个去执行的,并不能并行。

    (3)缺点

    permits 增加了控制的难度。

    例如,创建 Semaphore 是指定的 permits 的数量为 1, 但是执行 semaphore.acquire(2) 时指定要申请的 permits 数量为 2,总共的许可数有 1 个,但是申请 2 个,那么程序就会 block 住,因为当许可不够时,就会一直等待,使用 semephore 对象的任何线程都会阻塞。

    private Semaphore semaphore = new Semaphore(1);
    
    private void method() {
            semaphore.acquire(2); // 由于只有一个 1 个证书可申请,因此会一直阻塞。
            ...
            semaphore.release(2);
    }
    

    同样会造成 block 的情况还有一种情况,当执行 semaphore.acquire(3) 申请了两个许可证,但是后续 只执行了一次 semaphore.release() 操作或者执行的 release 许可证的的数量小于3,那么同样会造成 block。

    private Semaphore semaphore = new Semaphore(2);
    ...
    
    public void method() {
        semaphore.acquire(2);
        ...
        semaphore.release(); // 只 release 了一个证书,还需在执行一次 release 或者 release 执行证书数为 2
    }
    

    (4)permits 指定数量带来的扩展

    Semaphore 可以有效的对并发执的数量进行控制,因此可以应用在多个场景下。

    (1)同步操作。同一时间只能由一个线程进行操作。

    (2)动态调整性能。根据 CPU 的负载情况,动态调整当前任务并行处理的线程数。

    相关文章

      网友评论

        本文标题:Semaphore 多线程并发控制

        本文链接:https://www.haomeiwen.com/subject/jrgtvhtx.html