我正在实现一个带有ArrayList的程序,其中包含名为Bicycle的对象。
我维护一个变量来保存最大的自行车(用它的id测量)和一个变量来保存数组中的最大自行车索引。
我已经实现了2个函数 - addBicycle 和 removeMax ,它们是同步。
我担心当一个线程在addBicycle中而另一个线程在removeMax中时会发生什么 - 一个可能会添加新的自行车,这将是最大的,第二个线程将意外删除不再是最大值的旧值。
有没有办法防止它?一种方法禁止一个线程在add函数,另一个在remove函数,同时? 感谢
编辑:代码 -
public BicycleDataStructure() {
list = new ArrayList<T>();
maxBicycle = null;
maxBicycleIndex = 0;
}
public synchronized void addBicycle(T bToAdd) {
if (list.size() == 0) {
list.add(bToAdd);
maxBicycle = bToAdd;
maxBicycleIndex = 0;
} else {
for (int i = 0; i < list.size(); i++) {
//checks to add in the right position in the list
list.add(i, bToAdd); }
}
}
public synchronized Bicycle removeMaxBicycle() {
if (list.isEmpty()){
return null;
}
list.remove(maxBicycleIndex);
if (!list.isEmpty()) {
maxBicycle = collection.get(maxBicycleIndex- 1);
maxBicycleIndex-= 1;
}
}
答案 0 :(得分:1)
您在同一个对象锁上使用同步方法,因此由于以下原因而安全
两次调用同步方法是不可能的 相同的对象交错。当一个线程正在执行同步时 对象的方法,调用synchronized的所有其他线程 同一个对象块的方法(暂停执行)直到第一个 线程是用对象完成的。
其次,当同步方法退出时,它会自动建立 与任何后续调用a之前发生的关系 同一对象的同步方法。这保证了变化 所有线程都可以看到对象的状态。
答案 1 :(得分:-1)
使用您当前的实现,它将无法正常工作。 synchronized
关键字只是防止两个线程无法同时访问该代码块。然而,你所获得的是两种不同的方法,你所描述的情况可能会发生。
当您需要同步两种方法时,请考虑使用信号量:
private static final int MAX_AVAILABLE = 1;
private final Semaphore semaphore = new Semaphore(MAX_AVAILABLE, true);
public Bicycle removeMaxBicycle(){
semaphore.acquire();
//do your critical stuff
semaphore.release();
}
public void addBicycle(T bToAdd) {
semaphore.acquire();
//do your critical stuff
semaphore.release();
}
如果您对如何在Java中使用Semaphore有任何疑问,请查看此链接:https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Semaphore.html