pingh14

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Semaphore:动态增减信号量,用于控制对某资源访问的同一时间的并发量。类似于令牌,谁拿到令牌(acquire)就可以去执行了,如果没有令牌则需要等待。

【如何获取】:
semaphore.tryAcquire(),尝试获取,不阻塞。

semaphore.acquire(),没信号量可用时,将进行阻塞等,可以被中断。

acquireUninterruptibly():获取信号量,将进行阻塞,会忽略线程的中断而且不会抛出任何异常。

【如何释放】:
semaphore.release();
线程抛出各种异常,都别忘了在finally中释放信号量;
如果释放的比获取的信号量还多,例如获取了2个,释放了5次,那么当前信号量就动态的增加为5了,要注意。如下图所示:

 

例子:用信号量semaphore实现生产者与消费者

请仔细体会里面关于仓库的处理,

1 是如何保证入库时,如果仓库满就等待,

2 出库时,如果仓库无货就等待的。

3 以及对仓库只有10个库位的处理。

4 对同步问题的处理。

public class TestSemaphore {
    public static void main(String[] args) {
        for (int i = 0; i <= 3; i++) {
            new Thread(new Producer()).start();
            new Thread(new Consumer()).start();
        }
    }
    //仓库  
    static WareHouse buffer = new WareHouse();  
    //生产者
    static class Producer implements Runnable{
        static int num = 1;
        public void run() {
            int n = num++;
            while(true){
                try{
                    buffer.put(n);
                    System.out.println(">"+n);
                    Thread.sleep(10);
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    static class Consumer implements Runnable{
        public void run() {
            while (true) {
                try {
                    System.out.println("<"+buffer.take());
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    static class WareHouse{
        //非满锁
        final Semaphore notFull = new Semaphore(10);
        //非空锁
        final Semaphore notEmpty = new Semaphore(0);
        //互斥锁
        final Semaphore mutex = new Semaphore(1);
        //库存容量
        final Object[] items = new Object[10];
        int putPosi, takePosi, count;
        public void put(Object x)throws InterruptedException{
            try{
                notFull.acquire();
                mutex.acquire();
                items[putPosi] = x;
                if (++putPosi == items.length) {
                    putPosi = 0;
                }
                count++;
            }finally{
                notEmpty.release();
                mutex.release();
            }
        }
        public Object take()throws InterruptedException{
            notEmpty.acquire();
            mutex.acquire();
            try{
                Object x = items[takePosi];
                if(++takePosi == items.length){
                    takePosi = 0;
                }
                --count;
                return x;
            }finally{
                notFull.release();
                mutex.release();
            }
        }
    }
}

 也可以把Semaphore当锁来使用

当信号量的数量上限是1时,Semaphore可以被当做锁来使用。通过take和release方法来保护关键区域。请看下面的例子:

BoundedSemaphore semaphore = new BoundedSemaphore(1);
...
semaphore.acquire();
try{
  //critical section
} finally {
  semaphore.release();
}

 

 

posted on 2014-01-02 22:27  pingh14  阅读(634)  评论(0编辑  收藏  举报