在Java中根据监视器对象的特定属性同步线程

在Java中根据监视器对象的特定属性同步线程,java,multithreading,Java,Multithreading,我的程序模拟在存储库上工作。 必须同步的资源是存储库对象(用作监视器)中的数组单元格。 允许线程(RepoThreadclass)向数组的单元格值添加值或从中减去值,但仅当没有其他线程在同一单元格上执行相同操作时RepoThreads在不同的单元格上同时执行操作(加法/减法)。 当前正在处理的单元格将被视为“繁忙”,其索引将存储在HashMap中 我有这些课程(: 我的问题是,似乎没有发生冲突,因为我的add和remove方法是synchronized。这意味着当任何线程执行添加或移除操作时,

我的程序模拟在存储库上工作。 必须同步的资源是
存储库
对象(用作监视器)中的数组
单元格
。 允许线程(
RepoThread
class)向数组的单元格值添加值或从中减去值,但仅当没有其他线程在同一单元格上执行相同操作时
RepoThread
s在不同的单元格上同时执行操作(加法/减法)。 当前正在处理的单元格将被视为“繁忙”,其索引将存储在HashMap中

我有这些课程(:


我的问题是,似乎没有发生冲突,因为我的
add
remove
方法是
synchronized
。这意味着当任何线程执行添加或移除操作时,
存储库
对象被锁定,并且没有其他线程可以访问数组,因为整个对象被锁定,而不仅仅是忙碌的线程牢房


我应该做什么更改,这样线程就可以在存储库对象上做任何他们想做的事情,只要他们在一个非繁忙的
单元格
数组中做这些事情?

如果我理解你的问题,你想直接更精确地锁定单元格,对吗?如果是的话

一个选项是用单元格对象本身上的同步块替换同步(如果您创建了单元格对象的数组,这意味着您创建了一个单元格类)

另一种选择是通过一个ReentrantLock数组进行锁定,每个单元格一个

ReentrantLock [] locks = new ReentrantLock[nb];
// fill the array of ReentranLock, one per cell

locks[cellRank].lock();
try {
   // your stuff
} finally {
  lock[cellRank].unlock();
}

感谢您的回复。是否仍要使用同步块和无锁等待?如果使用同步块(第一种可能性),您仍然可以使用
cells[i]等待cells[i]。wait()
并使用
cells[i]唤醒它们。notifyAll()
。这不是你想要的吗?单元格是原始类型。你的第二个建议对我有效。谢谢!
public class RepoThread extends Thread {
    Repository mon;
    int id;
    int addOrRemove;
    int index;
    int amount;

    public RepoThread(Repository mon, int id, int addOrRemove, int index, int amount) {
        this.mon = mon;
        this.id = id;
        this.addOrRemove = addOrRemove;
        this.index = index;
        this.amount = amount;
    }

    public void run() {
        if (addOrRemove == 1) {
            mon.add(index, amount,id);
        }else if(addOrRemove==2){
            mon.remove(index, amount, id);
        }else{
            System.out.println("unknown operation requested");
        }
    }

}
public class TestRepository {
    public static void main(String[] args) {
        Repository repo = new Repository(10, 5);
        RepoThread remover1 = new RepoThread(repo, 1, 2, 5, 8);
        remover1.start();
        RepoThread remover2 = new RepoThread(repo, 2, 2, 5, 4);
        remover2.start();
        RepoThread adder1 =   new RepoThread(repo, 3, 1, 5, 4);
        adder1.start();
        RepoThread adder2 =   new RepoThread(repo, 4, 1, 5, 2);
        adder2.start();
        RepoThread adder3 =   new RepoThread(repo, 5, 1, 7, 4);
        adder3.start();
        RepoThread adder4 =   new RepoThread(repo, 6, 1, 5, 4);
        adder4.start();

    }
}
// Example
Cell [] cells = new Cell[nb];
// initialize the array as you need

// later on, in remove or add
synchronize (cells[i]) {
   // your stuff
}
ReentrantLock [] locks = new ReentrantLock[nb];
// fill the array of ReentranLock, one per cell

locks[cellRank].lock();
try {
   // your stuff
} finally {
  lock[cellRank].unlock();
}