java线程同步——信号量(Semaphore)

java.util.concurrent.Semaphore

信号量是一种计数器,用来保护一个或者多个共享资源的访问,它是并发编程的一种基础工具。

信号量通过计数器的方式来对资源进行访问控制

当其计数器值大于0时,表示有资源可以访问

当其计数器值等于0时,线程将进入休眠状态直到计数器值大于0


通过信号量的构造函数指定资源数量:

private final Semaphore semaphore  = new Semaphore(1);
表示该信号量的计数器值只能为0或者1,也称为二进制信号量

这样可以限制每次执行的线程只有一个


信号量的使用:

    private final Semaphore semaphore = new Semaphore(1);

    public void a() {
        try {
            //获取信号量的锁
            semaphore.acquire();
            //对共享资源进行操作
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //释放信号量
            semaphore.release();
        }
    }

信号量也有对应的tryAcquire()方法,和Lock的tryLock()一样


使用信号量控制资源的多副本并发访问控制

<pre style="background-color: rgb(255, 255, 255); font-family: Consolas; font-size: 10.5pt;"><pre name="code" class="java">public class TestSemaphore {
    //信号量控制资源的状态
    private final Semaphore semaphore;
    //资源数组,true表示可用(空闲)
    private boolean[] resources;
    //保护对资源数组的访问
    private Lock lock;
    //资源数量
    private int resourceCount = 3;

    public TestSemaphore() {
        semaphore = new Semaphore(resourceCount);
        resources = new boolean[resourceCount];
        for (int i = 0; i < resourceCount; i++) {
            resources[i] = true;
        }
        lock = new ReentrantLock();
    }

    public void doSth() {
        try {
            semaphore.acquire();
            int resource = getResource();
            //使用resource进行操作
            //任务完成,把对应的resource置为空闲
            resources[resource] = true;
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //释放信号量
            semaphore.release();
        }
    }

    /**
     * 获取空闲的资源
     *
     * @return 空闲的资源下标,没有就返回-1
     */
    private int getResource() {
        //资源下标
        int ret = -1;
        try {
            lock.lock();
            for (int i = 0; i < resources.length; i++) {
                if (resources[i]) {
                    ret = i;
                    resources[i] = false;
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return ret;
    }

}








發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章