美文网首页
理解Semaphore

理解Semaphore

作者: 饿了爸 | 来源:发表于2019-09-28 17:04 被阅读0次

Semaphore 是什么

Semaphore 信号量,是JDK的并发包中提供了一个非常有用的工具类。可以控制某个资源可被同时访问的个数,通过 acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可。
Semaphore实现的功能就类似厕所有5个坑,假如有10个人要上厕所,同时只能有5个人能够占用,当5个人中 的任何一个人让开后,其中等待的另外5个人中又有一个人可以占用了。另外等待的5个人中可以是随机获得优先机会,也可以是按照先来后到的顺序获得机会,这取决于构造Semaphore对象时传入的参数选项。单个信号量的Semaphore对象可以实现互斥锁的功能,并且可以是由一个线程获得了“锁”,再由另一个线程释放“锁”,这可应用于死锁恢复的一些场合。

适用场景

Semaphore可以用来做流量分流,特别是对公共资源有限的场景,比如数据库连接。
假设有这个的需求,读取几万个文件的数据到数据库中,由于文件读取是IO密集型任务,可以启动几十个线程并发读取,但是数据库连接数只有10个,这时就必须控制最多只有10个线程能够拿到数据库连接进行操作。这个时候,就可以使用Semaphore做流量控制。

原理

Semaphore实现主要基于java同步器AQS

应用实例

数据库连接有限,并发时,数据库操作通过信号量控制

public class SemaphoreTest {
    private static final int THREAD_COUNT = 40;
    private static boolean fair = false;
    private static Executor executor = Executors.newFixedThreadPool(THREAD_COUNT );
    public static void main(String[] args) {
        testSemaphore(false);
    }
    public static void testSemaphore(boolean fair){
         Semaphore semaphore = new Semaphore(10,fair);

        for (int i=0; i< THREAD_COUNT; i++) {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        //read data from file
                        semaphore.acquire();
                        println(Thread.currentThread().getName() + " acquire");
                        Thread.sleep(5000);//模拟数据库操作耗时
                        println(Thread.currentThread().getName() + " release");
                        semaphore.release();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                    }
                }
            });
        }
    }
}

如果以公平方式执行,则线程将会按到达的顺序(FIFO)执行,如果是非公平,则可以后请求的有可能排在队列的头部。
如果 fair 传的是 true,则各个线程公平竞争,即按照等待时间的长短决定谁先获取许可。执行结果如下,首选是线程 0、1、2...9 获取了许可,5s 后线程 10-19 获取了许可...,顺序基本上与创建线程并启动的先后顺序一致,也与各个线程等待的时间基本相符
如果 fair 传的是 false,运行的线程号很随机,与线程创建启动时间无关,也与线程等待时间无关。

小结

  • Semaphore 仅仅是对资源的并发访问的任务数进行监控,而不会保证线程安全,因此,在访问的时候,要自己控制线程的安全访问

相关文章

网友评论

      本文标题:理解Semaphore

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