我目前正在尝试实现受线程保护的链表。可实现的方法之一是take(),它删除最近添加的元素,如果列表为空,则等待添加元素。我对Java线程和同步的了解还很差,所以我想知道这种实现是否可行。特别是,我想知道如果在put()之前调用take()会发生什么情况。由于它们都使用相同的锁定对象,因此我感觉好像在put()之前调用了take()一样,take()的锁定从未释放,因此put()会被卡住,以尝试获取该lock()。这是我的实现
//Globals
private final Lock lock = new ReentrantLock();
final Condition notEmpty = lock.newCondition();
public boolean put(int address) {
Node newnode = new Node(null, null, address);
lock.lock();
if(first == null) {
try {
first = newnode;
last = newnode;
size++;
notEmpty.signal();
}
finally {
lock.unlock();
}
}
else {
if(contains(address) == true) {
remove(address);
}
first.prev = newnode;
newnode.next = first;
first = newnode;
size++;
}
return true;
}
为了
public int take() throws InterruptedException {
lock.lock();
try{
while(size() == 0)
notEmpty.await();
remove();
}
finally {
lock.unlock();
}
}
任何帮助将是巨大的!谢谢。
最佳答案
我认为您应该考虑使用“ java.util.Stack”。
Java堆栈已经同步,并且具有pop()和push()方法,您可以从take()和put()调用它们而不必担心锁。
现在,您需要做的就是在take()中等待,如果堆栈对象为空,则可以为堆栈对象设置一个侦听器,或者初始化一个类参数int takeCalled = 0
并在每次使用空堆栈调用take()时增加它:
public void take(){
if (stackObj.isempty()) takeCalled++;
else stackObj.pop();
}
如果
takeCalled > 0
然后在put()中进行简单检查以清空堆栈public void put(x){
stackObj.push(x);
while(!stackObj.isEmpty()) take();
}
我总是更喜欢使用同步构建中的实现,因为您不能授予免费的错误逻辑。例如,如果
first != null
,则您的看跌期权将不会释放锁定。关于java - 条件变量和锁的使用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34475170/