【并发编程】- Semaphore的公平与非公平信号量

241 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情

Semaphore的公平与非公平信号量

公平信号量是获取锁的顺序与线程启动的顺序有关,但不代表100%地获得信号量。

@Slf4j
public class SemaphoreService {
    private boolean isFair = false;
    private Semaphore semaphore = new Semaphore(1,isFair);

    public void testSemaphore(){
        try {
            semaphore.acquire();
            Thread.sleep(5000);
            log.info("线程名{}获取许可",Thread.currentThread().getName());
        } catch (InterruptedException e) {
            log.error("线程名:{} 进入了catch",Thread.currentThread().getName());
            e.printStackTrace();
        }finally {
            semaphore.release();
        }
    }
}

运行类代码如下:

public class TestSemaphore {
    public static void main(String[] args) {
        SemaphoreService service = new SemaphoreService();
        ThreadA[] threadAS = new ThreadA[5];
        for (int i = 0; i < 5 ; i++) {
            threadAS[i] = new ThreadA(service);
            threadAS[i].start();
        }
    }
}

程序结果如下:

15:11:21.344 [Thread-1] INFO com.ozx.concurrentprogram.semaphore.entity.ThreadA - 线程名 Thread-1 启动
15:11:21.344 [Thread-2] INFO com.ozx.concurrentprogram.semaphore.entity.ThreadA - 线程名 Thread-2 启动
15:11:21.344 [Thread-3] INFO com.ozx.concurrentprogram.semaphore.entity.ThreadA - 线程名 Thread-3 启动
15:11:21.345 [Thread-4] INFO com.ozx.concurrentprogram.semaphore.entity.ThreadA - 线程名 Thread-4 启动
15:11:21.345 [Thread-0] INFO com.ozx.concurrentprogram.semaphore.entity.ThreadA - 线程名 Thread-0 启动
15:11:26.353 [Thread-3] INFO com.ozx.concurrentprogram.semaphore.service.SemaphoreService - 线程名Thread-3获取许可
15:11:31.353 [Thread-2] INFO com.ozx.concurrentprogram.semaphore.service.SemaphoreService - 线程名Thread-2获取许可
15:11:36.353 [Thread-1] INFO com.ozx.concurrentprogram.semaphore.service.SemaphoreService - 线程名Thread-1获取许可
15:11:41.353 [Thread-4] INFO com.ozx.concurrentprogram.semaphore.service.SemaphoreService - 线程名Thread-4获取许可
15:11:46.354 [Thread-0] INFO com.ozx.concurrentprogram.semaphore.service.SemaphoreService - 线程名Thread-0获取许可

线程先启动,但是不一定先能获取许可,所以需要将Semaphore的公平锁置为true,公平信号量运行的效果是线程启动的顺序与调用Semaphore.acquire()的顺序有关,也就是先启动的线程优先获得许可。

方法tryAcquire()的使用

无参方法tryAcquire()的作用是尝试地获得1个许可,如果获取不到则返回false。此方法通常与if语句结合使用,其具有无阻塞的特点。无阻塞的特点可使线程不至于在同步点一直持续等待的状态,如果if语句判断不成立则线程会继续走else语句,程序会继续向下运行。