zoukankan      html  css  js  c++  java
  • 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 开发中,信号量的使用相对互斥锁来说较少,知名度没那么高,但在其他编程语言中使用较广。


    原文链接
     


     

  • 相关阅读:
    [zz]利用__FILE__, __LINE__, __FUNCTION__跟踪调试程序
    [zz]va_start() 和 va_end()函数应用
    [zz]shmdt与shmctl的区别
    [zz]GNU C 扩展之__attribute__ 机制简介 [2]
    Linux errno 错误含义速查
    过滤器的简介
    MyBatis中的原理
    文件上传
    mybatis实体为什么要提供一个无参的构造函数
    为什么要有无参构造方法
  • 原文地址:https://www.cnblogs.com/ConstXiong/p/12065843.html
Copyright © 2011-2022 走看看