我正在编写一个多人游戏,我需要一些代表游戏领域的解决方案。我实现了demo Synchronized2DArray类,但我认为这不是最好的方法。同步块锁定整个数组,而我只需要锁定一个单元格。是否可以只锁定一个细胞,或者还有其他方法可以改善性能?
class Synchronized2DArray {
private int[][] array;
public Synchronized2DArray(int size) {
array = new int[size][size];
}
public void setValue(int x, int y, int value) {
synchronized (array) {
array[x][y] = value;
}
}
public int getValue(int x, int y) {
synchronized (array) {
return array[x][y];
}
}
.................
}
答案 0 :(得分:1)
我认为真正的问题出在不同的级别:
getValue()
和setValue()
的调用序列化。上面的代码使得一个线程在另一个线程正在读取该值时设置一个值是不可能的。那里有一个微妙的区别。 所以,我的(非常通用的)答案是:你应该退一步,花一些时间思考
例如,您可以更改当前的锁定方法,而不是使用ReentrantReadWriteLock;允许无限读者访问;但要确保写作不会同时发生。
答案 1 :(得分:1)
GhostCat有一点,但我可以看到性能是在这里使用数组的可能原因。您可能希望在数组中保留一个play字段,并且您希望在此处使用某种基本类型的数组来避免大量对象的开销。虽然set和get方法可能会将整数映射到更有意义的东西,但这并不容易在Java中抽象出来。
更具体地说,你的问题: 您可以在数组的单个行或列上进行同步,如下所示:
synchronized (array[x]) { ... }
由于Java中的同步仅适用于对象,而不适用于原始数据类型(如int),因此无法轻松地仅在一个单元格上进行同步。 如果您使用对象作为单元格元素(例如Integer而不是int),则可以在单个单元格上进行同步,但内存和性能开销可能太大而无法使其成为一个好主意。