时间:2021-05-20
Semaphore的作用:
在java中,使用了synchronized关键字和Lock锁实现了资源的并发访问控制,在同一时间只允许唯一了线程进入临界区访问资源(读锁除外),这样子控制的主要目的是为了解决多个线程并发同一资源造成的数据不一致的问题。在另外一种场景下,一个资源有多个副本可供同时使用,比如打印机房有多个打印机、厕所有多个坑可供同时使用,这种情况下,Java提供了另外的并发访问控制--资源的多副本的并发访问控制,今天学习的信号量Semaphore即是其中的一种。
Semaphore实现原理初探:
Semaphore是用来保护一个或者多个共享资源的访问,Semaphore内部维护了一个计数器,其值为可以访问的共享资源的个数。一个线程要访问共享资源,先获得信号量,如果信号量的计数器值大于1,意味着有共享资源可以访问,则使其计数器值减去1,再访问共享资源。
如果计数器值为0,线程进入休眠。当某个线程使用完共享资源后,释放信号量,并将信号量内部的计数器加1,之前进入休眠的线程将被唤醒并再次试图获得信号量。
就好比一个厕所管理员,站在门口,只有厕所有空位,就开门允许与空侧数量等量的人进入厕所。多个人进入厕所后,相当于N个人来分配使用N个空位。为避免多个人来同时竞争同一个侧卫,在内部仍然使用锁来控制资源的同步访问。
Semaphore的使用:
Semaphore使用时需要先构建一个参数来指定共享资源的数量,Semaphore构造完成后即是获取Semaphore、共享资源使用完毕后释放Semaphore。
Semaphore semaphore = new Semaphore(10,true);semaphore.acquire();//do something heresemaphore.release();下面的代码就是模拟控制商场厕所的并发使用:
public class ResourceManage { private final Semaphore semaphore ; private boolean resourceArray[]; private final ReentrantLock lock; public ResourceManage() { this.resourceArray = new boolean[10];//存放厕所状态 this.semaphore = new Semaphore(10,true);//控制10个共享资源的使用,使用先进先出的公平模式进行共享;公平模式的信号量,先来的先获得信号量 this.lock = new ReentrantLock(true);//公平模式的锁,先来的先选 for(int i=0 ;i<10; i++){ resourceArray[i] = true;//初始化为资源可用的情况 } } public void useResource(int userId){ semaphore.acquire(); try{ //semaphore.acquire(); int id = getResourceId();//占到一个坑 System.out.print("userId:"+userId+"正在使用资源,资源id:"+id+"\n"); Thread.sleep(100);//do something,相当于于使用资源 resourceArray[id] = true;//退出这个坑 }catch (InterruptedException e){ e.printStackTrace(); }finally { semaphore.release();//释放信号量,计数器加1 } } private int getResourceId(){ int id = -1; lock.lock(); try { //lock.lock();//虽然使用了锁控制同步,但由于只是简单的一个数组遍历,效率还是很高的,所以基本不影响性能。 for(int i=0; i<10; i++){ if(resourceArray[i]){ resourceArray[i] = false; id = i; break; } } }catch (Exception e){ e.printStackTrace(); }finally { lock.unlock(); } return id; } } public class ResourceUser implements Runnable{ private ResourceManage resourceManage; private int userId; public ResourceUser(ResourceManage resourceManage, int userId) { this.resourceManage = resourceManage; this.userId = userId; } public void run(){ System.out.print("userId:"+userId+"准备使用资源...\n"); resourceManage.useResource(userId); System.out.print("userId:"+userId+"使用资源完毕...\n"); } public static void main(String[] args){ ResourceManage resourceManage = new ResourceManage(); Thread[] threads = new Thread[100]; for (int i = 0; i < 100; i++) { Thread thread = new Thread(new ResourceUser(resourceManage,i));//创建多个资源使用者 threads[i] = thread; } for(int i = 0; i < 100; i++){ Thread thread = threads[i]; try { thread.start();//启动线程 }catch (Exception e){ e.printStackTrace(); } } } }最后,Semaphore除了控制资源的多个副本的并发访问控制,也可以使用二进制信号量来实现类似synchronized关键字和Lock锁的并发访问控制功能。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
一、信号量(Semaphore)信号量(Semaphore)是由内核对象维护的int变量,当信号量为0时,在信号量上等待的线程会堵塞,信号量大于0时,就解除堵塞
java中使用Semaphore构建阻塞对象池Semaphore是java5中引入的概念,叫做计数信号量。主要用来控制同时访问某个特定资源的访问数量或者执行某个
Java通过代码模拟高并发可以以最快的方式发现我们系统中潜在的线程安全性问题,此处使用Semaphore(信号量)和CountDownLatch(闭锁)搭配Ex
Semaphore是一个计数信号量,它的本质是一个共享锁。信号量维护了一个信号量许可集。线程可以通过调用acquire()来获取信号量的许可;当信号量中有可用的
1.信号量Semaphore先说说Semaphore,Semaphore可以控制某个资源可被同时访问的个数,通过acquire()获取一个许可,如果没有就等待,