死锁解决方案





0/5 (0投票)
使用 ExecutorService 和 LiveLockSolution 接口解决死锁问题
Java 并发问题简介
Java,凭借其并发 API,为死锁问题提供了良好的解决方案:使用 java.util.concurrent.locks
接口及其实现,例如 ReentrantLock
类;而对于解决活锁问题,在线文档并不多。
饥饿是与并发相关的另一个问题,请参阅参考资料部分以深入了解。
什么是活锁
活锁的定义,来自 教程:并发
一个线程通常是对另一个线程的动作做出反应。如果另一个线程的动作也是对另一个线程的动作做出反应,那么就可能导致活锁。与死锁一样,活锁线程无法继续前进。但是,这些线程并没有被阻塞——它们只是太忙于相互响应而无法恢复工作。这类似于两个人试图在走廊里互相让路:Alphonse 向左移动让 Gaston 通过,而 Gaston 向右移动让 Alphonse 通过。看到他们仍然互相阻碍,Alphone 向右移动,而 Gaston 向左移动。他们仍然互相阻碍,所以……
我的解决方案
我提出的解决方案使用了 java.util.concurrent.ExecutorService
接口和由我创建的 LiveLockSolution
接口。
如何使用 LiveLockSolution 接口
使用 LiveLockSolution
,我将记住在用于数据并发的类中编写一个方法来解决活锁问题。
public interface LiveLockSolution {
public void liveLockSolution();
}
这是使用锁并实现 LiveLockSolution
的 Product
类。
public class Product implements LiveLockSolution{
private int quantity;
private boolean endLoop;
private ReentrantLock lock;
private Condition cond;
public Product(ReentrantLock lock) {
this.endLoop = false;
this.quantity = 0;
this.lock = lock;
this.cond = lock.newCondition();
}
public void produce() {
lock.lock();
try {
this.quantity++;
System.out.println("Q:" + this.quantity);
cond.signalAll();
} finally {
lock.unlock();
}
}
/**
* It consumes a product, if there isn't a product wait
*/
public void consume() {
lock.lock();
try {
while(this.endLoop == false && this.quantity == 0) {
cond.await();
}
if(this.endLoop == false) {
this.quantity--;
System.out.println("Q:" + this.quantity);
}
cond.signalAll();
} catch(Exception ex) {
ex.printStackTrace();
} finally {
lock.unlock();
}
}
/**
* To ending all waiting threads that use Product
*/
@Override
public void liveLockSolution() {
lock.lock();
try {
this.endLoop = true; //it says to consume to don't wait any more
cond.signalAll();
} finally {
lock.unlock();
}
}
Consumer
和 Productor
类现在包含在 zip 文件中。
如何使用 ExecutorService 接口
ExecutorService
接口是主代码中的执行者(参见下一个示例):使用 awaitTermination
方法,在停止所有线程后,我们知道执行器池中是否有正在运行的线程,因此使用 liveLockSolution
来解决活锁问题。
public static void main(String[] args) {
try {
ReentrantLock lock = new ReentrantLock();
Product obj = new Product(lock);
Consumer cons = new Consumer(obj);
Consumer cons2 = new Consumer(obj);
Producer prod = new Producer(obj);
System.out.println("Start concurrency\n\n");
ExecutorService es = Executors.newCachedThreadPool();
//executes threads
es.execute(cons);
es.execute(cons2);
es.execute(prod);
//lets execute threads for a second
Thread.sleep(1000);
//stops the threads
prod.stop();
cons.stop();
cons2.stop();
//to showdown the executor
es.shutdown();
//waiting running threads
while(es.awaitTermination(100, TimeUnit.MILLISECONDS) == false) {
System.out.println("Waiting threads closing");
obj.liveLockSolution(); //solve livelock
}
System.out.println("Concurrency end");
} catch (InterruptedException e) {
e.printStackTrace();
} catch(Exception e) {
e.printStackTrace();
}
}
就这样,各位!
参考文献
历史
- 首次发布:2011 年 11 月