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

Java 在一个线程添加项目和一个线程删除项目时同步最大值,java,multithreading,synchronization,thread-safety,Java,Multithreading,Synchronization,Thread Safety,我正在用ArrayList实现一个程序,其中包含名为Bicycle的对象 我在数组中维护了一个变量来保存max Bicycle(通过它的id测量),以及一个变量来保存max Bicycle索引 我已经实现了两个函数-addBicycle和removeMax,它们是同步的 我担心当一个线程在addBicycle中而另一个线程在removeMax中时会发生什么-一个线程可能会添加新的bicycle,这将是最大值,而第二个线程会意外地删除不再是最大值的旧值 有什么办法可以预防吗?一种禁止一个线程同时在

我正在用ArrayList实现一个程序,其中包含名为Bicycle的对象

我在数组中维护了一个变量来保存max Bicycle(通过它的id测量),以及一个变量来保存max Bicycle索引

我已经实现了两个函数-addBicycleremoveMax,它们是同步的


我担心当一个线程在addBicycle中而另一个线程在removeMax中时会发生什么-一个线程可能会添加新的bicycle,这将是最大值,而第二个线程会意外地删除不再是最大值的旧值

有什么办法可以预防吗?一种禁止一个线程同时在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;

    } 


}
public BicycleDataStructure(){
列表=新的ArrayList();
maxBicycle=null;
maxBicycleIndex=0;
}
公共自行车(T bToAdd){
if(list.size()==0){
列表。添加(b加载);
maxBicycle=B负载;
maxBicycleIndex=0;
}否则{
对于(int i=0;i
对于您当前的实现,它不会像您期望的那样工作。
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中使用信号量有任何疑问,请签出此链接:

您正在同一个对象锁上使用同步方法,因此出于以下原因,它是安全的

不可能在上两次调用同步方法 要交错的相同对象。当一个线程正在执行同步 方法,调用同步的所有其他线程 相同对象块的方法(暂停执行),直到第一个 线程是用对象完成的

其次,当同步方法退出时,它会自动建立 与任何后续调用的关系之前发生 同一对象的同步方法。这保证了这些变化 对象的状态对所有线程都可见


“当一个线程在addBicycle中而另一个线程在removeMax中时”,如果它们在同一个监视器上同步,则不能发生。@AndyTurner为什么?如果一个函数是同步的,这意味着该函数中不能同时有两个线程,但这是两个不同的函数如果它们是同一实例上的同步方法,一次只能有一个线程调用其中任何一个方法。正如@AndyTurner所说,这里的大问题是使用哪个锁来同步这两个方法,你能出示你的密码吗?(我和Andy一样,假设你使用的是对象的内在锁,我更喜欢确认)@asettouf不,使用同步列表不会使事情变得安全,因为OP有先检查后行动的操作,这不是原子操作,也会作用于单独的字段(maxBicycle,maxBicycleIndex)。这是完全错误的。两个方法都使用相同的锁(这个),因此,如果一个线程执行一个方法,那么其他线程就不能执行另一个。