博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
当面试官问我JDK Semaphore的原理时,我笑了
阅读量:6244 次
发布时间:2019-06-22

本文共 3621 字,大约阅读时间需要 12 分钟。

原理:Semaphore是用来保护一个或者多个共享资源的访问,Semaphore内部维护了一个计数器,其值为可以访问的共享资源的个数。一个线程要访问共享资源,先获得信号量,如果信号量的计数器值大于1,意味着有共享资源可以访问,则使其计数器值减去1,再访问共享资源。

如果计数器值为0,线程进入休眠。当某个线程使用完共享资源后,释放信号量,并将信号量内部的计数器加1,之前进入休眠的线程将被唤醒并再次试图获得信号量。
就好比一个厕所管理员,站在门口,只有厕所有空位,就开门允许与空厕数量等量的人进入厕所。多个人进入厕所后,相当于N个人来分配使用N个空位。为避免多个人来同时竞争同一个侧卫,在内部仍然使用锁来控制资源的同步访问

1、下面,我模仿jdk Semaphore的实现原理,自己实现一遍

package com.jacky;import java.util.concurrent.Semaphore;import java.util.concurrent.locks.AbstractQueuedSynchronizer;/** * Created by jacky on 2018/2/13. */public class MySemaphore {    private Sync sync;    public MySemaphore(int permits){       sync = new NonFairSync(permits);    }    public MySemaphore(int permits,boolean fair){        sync = fair ? new FairSync(permits) : new NonFairSync(permits);    }    static class Sync extends AbstractQueuedSynchronizer{        Sync(int permits) {            setState(permits);        }        @Override        protected boolean tryReleaseShared(int arg) {            for (;;){                int oldState = getState();                int newState = oldState+arg;                if (compareAndSetState(oldState,newState)){                    return true;                }            }        }    }    static final class FairSync extends Sync{        FairSync(int permits) {            super(permits);        }        @Override        protected int tryAcquireShared(int arg) {            for(;;){                if (hasQueuedPredecessors()){                    return -1;                }                int oldState = getState();                int newState = oldState-arg;                if (newState <0 || compareAndSetState(oldState,newState)){                    return  newState;                }            }        }    }    static final class NonFairSync extends Sync{        NonFairSync(int permits) {            super(permits);        }        @Override        protected int tryAcquireShared(int arg) {            for(;;){                int oldState = getState();                int newState = oldState-arg;                if (newState <0 || compareAndSetState(oldState,newState)){                    return  newState;                }            }        }    }    /**     * 获取许可证     */    public void acquire(){        try {            sync.acquireSharedInterruptibly(1);        } catch (InterruptedException e) {            e.printStackTrace();        }    }    /**     * 释放许可证     */    public void release(){       sync.releaseShared(1);    }}复制代码

2、接下来,我们来测试一下

package com.jacky;import java.util.concurrent.Semaphore;/** * Created by jacky on 2018/2/12. */public class SemaphoreDemo {    public static void main(String[] args) {        //Semaphore semaphore = new Semaphore(2, true);        MySemaphore semaphore = new MySemaphore(2, true);        Runnable runnable = new Runnable() {            @Override            public void run() {                Thread thread = Thread.currentThread();                System.out.println("semaphore start:"+thread.getName());                try {                    semaphore.acquire();                    Thread.sleep(2000);                } catch (InterruptedException e) {                    e.printStackTrace();                }                semaphore.release();                System.out.println("semaphore end:"+thread.getName());            }        };        for (int i=0;i<10;i++){            Thread thread = new Thread(runnable, "t" + i);            thread.start();            try {                Thread.sleep(100);            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}复制代码

喜欢本文的朋友,欢迎关注,本人的微信公众号,“咖啡牧羊人”

转载地址:http://btvia.baihongyu.com/

你可能感兴趣的文章
汇编实验九
查看>>
哈夫曼编码
查看>>
go语言学习之闭包函数
查看>>
javax.servlet.http.HttpServletRequest; 不存在
查看>>
类型自动转换规则
查看>>
kvm-控制台登陆配置
查看>>
SpringAOP
查看>>
有赞MySQL自动化运维之路—ZanDB
查看>>
String与常量池(JDK1.8)
查看>>
lightoj 1031(dp)
查看>>
SQL Server转sqlite数据库
查看>>
python print和strip
查看>>
2016学年第一学期软件工程第二次作业
查看>>
Powershell检查邮件队列设置阈值,通过html形式进行邮件告警
查看>>
痞子衡嵌入式:恩智浦i.MXRT系列微控制器量产神器RT-Flash用户指南
查看>>
PHP学习笔记1
查看>>
MySQL学习1
查看>>
14.linux下复制粘贴
查看>>
网络编程
查看>>
List数据转Map数据并进行分组排序
查看>>