• JAVA多线程之Semaphore


    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();
    }
  • 相关阅读:
    C# 特性(Attribute)学习
    ASP.NET Request.MapPath() 与 Server.MapPath()
    Asp.net对http request 处理的全过程!
    保存网址
    寻找silverlight高手帮忙解决问题,谢谢,
    基于.Net Framework的N层分布式应用开发
    VB.NET 代码转为C#
    刚刚开通博客噢 。欢迎大家光临啊
    配置本地服务器的几种方式
    前端必备工具 (记录)
  • 原文地址:https://www.cnblogs.com/pingh/p/3502760.html
Copyright © 2020-2023  润新知