当面试官问我JDK Semaphore的原理时,我笑了

原理: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();
            }
        }
    }
}
复制代码

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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值