下面是关于semaphore 的死锁的例子。主要自己学习thinking in java 上面的semaphore的例子的时候不仔细。结果将checkout() 和 checkin() 方法都加上了synchronized. 导致了死锁的问题。代码如下:
public class SemaphoreDemo {
final static int SIZE = 10;
public static void main(String[] args) throws Exception {
final Pool<Fat> pool = new Pool<>(Fat.class, SIZE);
ExecutorService exec = Executors.newCachedThreadPool();
for(int i=0; i<SIZE; i++){
exec.execute(new CheckoutTask<Fat>(pool));
}
System.out.println("All checkout task created.");
TimeUnit.SECONDS.sleep(2);
List<Fat> list = new ArrayList<>();
for(int i=0; i<SIZE; i++){
Fat f = pool.checkout();
System.out.println(i +": main() thread checkd out");
f.operation();
list.add(f);
}
Future<?> blocked = exec.submit(new Runnable() {
@Override
public void run() {
try {
pool.checkout();//这里阻塞住了。
} catch (InterruptedException e) {
//acceptable way to exit.
}
}
});
TimeUnit.SECONDS.sleep(2);
blocked.cancel(true);//break out of blocked call.
System.out.println("checking in objects in "+list);
for(Fat f : list){
pool.checkin(f);
}
for(Fat f : list){//second check in ignored.
pool.checkin(f);
}
exec.shutdownNow();
}
}
//代理
class Pool<T> {
private int size;
//资源类型是一样的。
private List<T> holder = new ArrayList<>();
private volatile boolean[] checkedOut;//跟踪checkedout的对象。
private Semaphore avaliable;
public Pool(Class<T> resourceType, int size){
this.size = size;//这个size没有赋值,导致没有调试出来。
checkedOut = new boolean[size];
avaliable = new Semaphore(size);//permits.
//instance resources.
try{
for(int i=0; i<size; i++){
holder.add(resourceType.newInstance());
// System.out.println(holder.get(i));
}
}catch(Exception e){
throw new RuntimeException(e);
}
}
//对外提供接口
public synchronized T checkout() throws InterruptedException{
System.out.println(Thread.currentThread().getName());
avaliable.acquire();//main 在这里占用着synchronized. 但是在调用avaliable.acquire()的时候阻塞了。
return getItem();
}
public synchronized void checkin(T item){
boolean released = releaseItem(item);
if(released){
avaliable.release();
}
}
private synchronized T getItem(){
for(int i=0; i<size; i++){
if(!checkedOut[i]){
checkedOut[i] = true;
return holder.get(i);
}
}
return null;//semaphore prevents reaching here.
}
private synchronized boolean releaseItem(T item){
int index = holder.indexOf(item);
if(index == -1){
return false;
}
if(checkedOut[index]){
checkedOut[index] = false;
return true;
}
return false;
}
}
class Fat{
private static int counter = 0;
private final int id = counter++;
public Fat(){}
public void operation(){
System.out.println(this+"do operation.");
}
@Override
public String toString() {
return "id: "+id;
}
}
class CheckoutTask<T> implements Runnable{
private Pool<T> pool;
private static int counter = 0;
private final int id = counter++;
public CheckoutTask(Pool<T> pool) {
this.pool = pool;
}
@Override
public void run() {
try{
T resource = pool.checkout();
System.out.println(this+" checkedout "+ resource);
TimeUnit.SECONDS.sleep(1);
System.out.println(this+" checkedin "+resource);
pool.checkin(resource);
}catch(InterruptedException e){
}
}
@Override
public String toString() {
return "CheckoutTask "+id+" ";
}
}
死锁出现的原因是:
CheckoutTask 在执行run() 的时候,在方法的内部执行完checkout() 后 ,size 个线程都释放了checkout() 方法上的synchronized修饰的对象的锁,而此时。main ()方法中的 Fat f = pool.checkout(); 执行。由于size 个CheckoutTask 线程还在占用着Semaphore。 所以main 线程在此阻塞。但是main 线程确拿着checkout() 方法上的synchronized 修饰的对象锁。这样就形成了循环等待。即size线程占用着Semaphore ,等待main释放checkout()方法的对象锁。而main 线程占用着checkout() 方法上的对象锁,而等待着使用Semaphore。
自己的语言表达不是很好,有问题希望大家随时指教。
分享到:
相关推荐
semaphore完整搭建方案,包括帮助文档、程序源码、可执行程序。按照帮助文档完整搭建可视化ansible部署解决方案
semaphore开发源码,ansible可视化部署服务程序,支持界面操作。
Semaphore的使用及其方法的使用。
semaphore控制多线程循序执行,网上 找的例子更改的希望对大家有用
Semaphore T-BOX System OverviewPDF,Semaphore T-BOX System Overview
mutex和semaphore互斥程序实例
Semaphore 源码解析 通过使用Semaphore可以在高并发场景进行限流控制处理
关于Android变成中的信号量semaphore,在使用过程中我们往往搞不清楚其信号量的申请和使用。这里主要针对信号量初始值为零的情况做介绍,其他情况不做讨论。初始值为零的情况较少使用,部分代码中的这个情况往往让...
Semaphore是计数信号量。Semaphore管理一系列许可证。每个acquire方法阻塞,直到有一个许可证可以获得然后拿走一个许可证;每个release方法增加一个许可证,这可能会释放一个阻塞的acquire方法。然而,其实并没有...
Semaphore_TBOX_产品-软件及系统功能
Linux下多线程编程-Pthread与Semaphore的使用.doc
使用信号量(Semaphore)实现线程的同步
多线程(C++)同步Semaphore
Semaphore进程间通讯测试源码,CreateSemaphoreW,OpenSemaphore,ReleaseSemaphore,WaitForSingleObjectEx
windows下安装cygwin,编译darknet时缺少的三个头文件,下载后复制到darknet下include文件夹内即可
本文分析了内核同步及互斥的几种机制Waitqueue、Event及Semaphore的实现,详细分析了其实现流程。Event及Semaphore本质...总结了静态定义及动态初始化数据结构的相关规则,这对于自定义的数据类型具有重要的借鉴意义。
信号量+共享存储区的进程间通信,互斥、同步
Semaphore Semaphore分为单值和多值两种,前者只能被一个线程获得,...单个信号量的Semaphore对象可以实现互斥锁的功能,并且可以是由一个线程获得了“锁”,再由另一个线程释放“锁”,这可应用于死锁恢复的一些场
Ansible-semaphore.zip,可供选择的开源towerrelease,ansible是一个简单而强大的自动化引擎。它用于帮助配置管理、应用程序部署和任务自动化。
C#语言Semaphore类用法实例,多线程 用于有多个同类型共享资源(比如端口)时,如何协调端口分配给线程访问资源的问题,是一个简单模拟实例(源代码)。