概述
资源并发访问控制
有时候我们需要保护共享资源,限制同时访问共享资源的线程数。这种场景可以使用信号量(Semaphore)机制。信号量是一种计数器,可以用来保护一个或多个共享资源。
当线程访问共享资源时,必须要先获得信号量。如果信号量内部计数器大于0,则信号量减1,然后允许访问这个共享资源。计数器大于0意味着有可以使用的资源,因为线程被允许使用其中一个。如果信号量的计数器等于0,信号量将会把线程置入休眠直至计数器大于0.计数器等于0意味着所有的共享资源已经被其他线程使用了,所以需要访问共享资源的线程等待。
线程使用完某个共享资源后,信号量必须被释放,以便其他线程能够访问共享资源。释放信号量将使信号量内部计数器增加1。
关于信号量和synchronized以及Lock的区别:信号量的目的是控制共享资源的并发访问数量,以保证共享资源的可用;而synchronized和Lock的目的是对临界区的并发进行控制,以保证共享资源只有一个线程可以访问。
下面以示例来说明信号量的作用和如何使用。示例演示只有一个资源的资源池,同一时间只允许一个线程获得资源,其他线程必须等待此线程释放信号量后才能获得信号量。并发线程会从资源池获取资源。获取资源的线程需要先获得信号量,然后使用资源,最后释放资源。如果获取资源时资源池没有空闲资源,那么此线程会一直等待。代码如下:
public class SemaphoreDemo {
public static void main(String[] args){
ResourceController resourceController = new ResourceController();
ResourceAccessor accessor = new ResourceAccessor(resourceController);
Thread[] threads = new Thread[5];
System.out.println("main:创建5个资源访问线程");
for(int i=0 ;i<threads.length; i++){
threads[i] = new Thread(accessor);
}
System.out.println("main:启动5个资源访问线程");
for(int i=0; i<threads.length; i++){
threads[i].start();
}
System.out.println("main:等待5个资源访问线程");
for(int i=0; i<threads.length; i++){
try {
threads[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("main:退出");
}
}
/** 资源访问器 **/
class ResourceAccessor implements Runnable{
private ResourceController resourceController;
ResourceAccessor(ResourceController resourceController){
this.resourceController = resourceController;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + ":申请资源");
resourceController.acquire();
long delay = (long)(Math.random()*1000);
try {
System.out.println(Thread.currentThread().getName() + ":取得资源");
Thread.sleep(delay);
System.out.println(Thread.currentThread().getName() + ":操作完成");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
resourceController.release();
System.out.println(Thread.currentThread().getName() + ":释放资源");
}
}
}
/** 资源控制器 **/
class ResourceController {
private int resources;
private Semaphore semaphore;
public ResourceController(){
//只允许一个线程并发访问
semaphore = new Semaphore(1);
}
/** 取得资源 **/
public void acquire(){
try {
//取得信号量
semaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/** 释放资源 **/
public void release(){
//释放信号量
semaphore.release();
}
}
程序运行日志:
main:创建5个资源访问线程
main:启动5个资源访问线程
main:等待5个资源访问线程
Thread-4:申请资源
Thread-4:取得资源
Thread-2:申请资源
Thread-0:申请资源
Thread-3:申请资源
Thread-1:申请资源
Thread-4:操作完成
Thread-4:释放资源
Thread-2:取得资源
Thread-2:操作完成
Thread-2:释放资源
Thread-0:取得资源
Thread-0:操作完成
Thread-0:释放资源
Thread-3:取得资源
Thread-3:操作完成
Thread-3:释放资源
Thread-1:取得资源
Thread-1:操作完成
Thread-1:释放资源
main:退出
最后
以上就是洁净鸡为你收集整理的2.7.资源并发访问控制资源并发访问控制的全部内容,希望文章能够帮你解决2.7.资源并发访问控制资源并发访问控制所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复