在一个线程添加项目和一个线程删除项目时同步最大值

时间:2017-06-21 11:34:14

标签: java multithreading synchronization thread-safety

我正在实现一个带有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;

    } 


}

2 个答案:

答案 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