线程安全资源池的实现

对于一些计算机上有限的资源(例如端口),或者创建/销毁的开销比较大的资源(例如线程,连接),通常会创建一个资源池,在需要使用资源时,由资源池分配,如果暂时没有可用的资源则需要等待。使用之后再将资源返还给资源池(如果还可以复用的话)。这样做可以提高资源利用效率,避免某一进程占用过多资源,也可以提高性能。

资源池一些常见的例子,包括数据库连接池、线程池、对象池等等。在实际应用中,通常需要在多线程环境下对资源池进行访问,因此资源池的需要做到线程安全。

正在进行的一个项目中的连接池实现:

https://github.com/duoertai/SagresMemcachedClient/blob/master/src/kyrat/sagres/ConnectionPool.java

大体思路类似,所以由连接池推广到需要线程安全的各类资源池。

  1. 资源池可以在初始化时创建一定数量的资源,当然这是可选的。
  2. 资源池要确定最大资源数目,总体资源数目不能超过这个数值。
  3. 资源池要记录现在可用的资源数。
  4. 资源池要记录当前总体资源数目,即资源池内可用资源数+交由请求者使用的资源数

向资源池请求资源时

  • 如果有可用的资源则交给请求者
  • 如果没有可用资源,如果总体资源数小于最大资源数,则创建新的资源并交由请求者使用,否则需要请求者等待

在多线程访问的环境下,需要对线程池的一些操作在必要的步骤加锁进行同步,然而如果在不要的步骤加了锁,则会导致性能降低。

在请求者请求资源时先lock,修改可用资源数,尝试获取资源,再unlock,如果没有得到可用资源,则根据上述原则创建新的资源,创建新资源部分,因为还没加入池中,不属于边界资源,这一步不需要加锁同步。只要在初始化资源池时状态是一致的,之后多线程获取资源的情况下也是一致的。

在请求者释放资源时,则需要先lock,将资源放回池中,修改可用资源数,unlock。即整个释放的过程都需要进行同步。这样才可以保证资源池状态一致性。否则可能出现一个线程释放资源时,修改了可用资源数,却没有将资源释放,然后被挂起,另一线程则发现还有可用的资源,然而却无法获取,从而创建了新的资源,造成数据不一致。

用一个日常生活中的例子打个比方:例如图书馆向外借书,《Java编程思想》有10本,最多可借出20本,如果不够则图书馆会额外订购,图书馆账目上记录了总共10本书,最初向外借出0本,还剩10本可借。每次借书时,需要同时完成修改账目和拿走一本书的操作,如果图书馆已经没有此书了,且总共数量不足20本,图书馆会告诉借书者已经订购了一本新的,此时借书者不需要继续占据柜台,可以让下一个借书者来借,当前借书者只需要等待图书馆给他购买的新书就可以。在借书者还书的时候,则需要完成修改账目和还书操作,才可以保证数据一致性,否则可能导致账目错误,造成额外订购了新书,从而使总数量超过20本。

转载于:https://my.oschina.net/u/3705207/blog/1558806

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值