• Java中的信号量Semaphore


    信号量的实现模型一般包括:1个计数器、1个等待队列、3个方法(需要保证原子性)

    Semaphore 实现的伪代码(JDK 中 Semaphore 是基于 AbstractQueuedSynchronizer 实现,可以指定是否公平):

    class Semaphore{
        //计数器
        int count;
        
        //等待队列
        Queue queue;
        
        //初始化
        Semaphore(int c){
            this.count=c;
        }
        
        //获取许可证
        void acquire(){
            count--;
            if(count<0){
                //将当前线程插入等待队列
                //阻塞当前线程
            }
        }
        
        //获取许可证
        void release(){
            count++;
            if(count<=0) {
                //移除等待队列中的某个线程
                //唤醒某个线程
            }
        }
    }

    使用信号量实现互斥锁效果:

    package constxiong.interview;
    
    import java.util.concurrent.Semaphore;
    
    /**
     * 测试使用信号量实现锁的效果
     * @author ConstXiong
     * @date 2019-12-18 14:18:47
     */
    public class TestSemaphore {
    
        private static int count;
        
        private static Semaphore semaphore = new Semaphore(1); 
        
        public static void main(String[] args) {
            for (int i = 0; i < 100; i++) {
                new Thread(() -> {
                    add();
                    System.out.println(count);
                }).start();
            }
        }
        
        private static void add() {
            try {
                semaphore.acquire();
                Thread.sleep(100);
                count++;
            } catch(InterruptedException e) {
                e.printStackTrace();
            } finally {
                semaphore.release();
            }
        }
        
    }

    除了能实现互斥锁,信号量还可以做到允许多个线程访问同一个临界区,这是它与互斥锁一个较大的区别点。

    将代码进行修改,实现限流功能:

    package constxiong.interview;
    
    import java.util.concurrent.Semaphore;
    import java.util.concurrent.atomic.AtomicInteger;
    
    /**
     * 测试使用信号量实现限流的效果
     * @author ConstXiong
     * @date 2019-12-18 14:18:47
     */
    public class TestSemaphore {
        
        private static AtomicInteger acount = new AtomicInteger(0);
        
        private static Semaphore semaphore = new Semaphore(10); 
        
        public static void main(String[] args) {
            testAddAtomic();
        }
        
        /**
         * 测试允许十个线程并发递增 acount
         */
        private static void testAddAtomic() {
            for (int i = 0; i < 100; i++) {
                new Thread(() -> {
                    System.out.println(addAtomic());
                }).start();
            }
        }
        
        private static int addAtomic() {
            try {
                semaphore.acquire();
                Thread.sleep(100);
                return acount.incrementAndGet();
            } catch(InterruptedException e) {
                e.printStackTrace();
            } finally {
                semaphore.release();
            }
            return -1;
        }
        
    }

    在实际的 Java 开发中,信号量的使用相对互斥锁来说较少,知名度没那么高,但在其他编程语言中使用较广。


    原文链接
     


     

  • 相关阅读:
    [已读]精通AngularJS
    [在读]HTML5数据推送应用开发
    [未读]深入浅出node.js
    [已读]用Angularjs开发下一代web应用
    [在读]Secrets of the javascript Ninja
    Element ui select同时获取value和label的值
    Element ui tree树形控件获取父节点id
    Element ui tree结合Vue使用遇到的一些问题(一)
    vue数组检测更新问题
    css3实现流星坠落效果
  • 原文地址:https://www.cnblogs.com/ConstXiong/p/12065843.html
Copyright © 2020-2023  润新知