同步缓存矩阵

时间:2013-05-28 21:15:18

标签: java multithreading caching mutual-exclusion

我在学校的java项目上工作,你必须处理多线程程序。 我需要一个在多个线程之间共享的类,它基本上是一个必须管理并发访问的值矩阵,它看起来像:

public class CacheMatrix{
private MyType[][] cachedItems;

public CacheMatrix(int size){
    this.cachedItems = new MyType[size][size];
}
public MyType readItem(int x, int y){...}
public void storeItem(int x, int y, MyType item){...}
}

我正要使用ReentrantReadWriteLock矩阵来管理它,每个项目一个,但我意识到矩阵大小大约是10 ^ 3 X 10 ^ 3所以我会有100万个锁!

你认为这是要走的路吗? (可以创建这么多锁吗?)

考虑到使用此类的线程数量限制为N(N范围从2到8),您能找到一种更好的方法,几乎​​只保留最小互斥但使用较少的锁定吗?

感谢您的支持!

4 个答案:

答案 0 :(得分:1)

您可以考虑实施lock striping以减少锁定数量并保持性能。

基本上,会创建一个包含mylockscount = min(concurrencylevel, size)锁的内部数组。 无论何时发生读/写操作,您都可以锁定,例如mylocks[somehashfunction(x, y) % mylockscount]

这样,锁的数量应该只与并发线程数一致,而不是矩阵的大小。

答案 1 :(得分:0)

另一种选择是将MyType[][]替换为AtomicReference<MyType>[][];在这种情况下,void storeItem将变为boolean storeItem(int x, int y, MyType oldValue, MyType newValue),如果oldValue不等于当前在[x][y]保持的值(在您要调用的表面下AtomicReference#compareAndSet(oldValue, newValue),则返回false })。这样你就没有任何锁,你需要在storeItem返回false的情况下实现重试逻辑

如果MyType是基元,例如int,然后使用适当的原子基元,例如AtomicInteger代替AtomicReference

答案 2 :(得分:0)

关于只是使访问方法同步?

public synchronized MyType readItems(...){...}

答案 3 :(得分:0)

我想到了两种可能的情景:

1)使用单个锁。这有点天真,但它可以解决你的问题。

2)仅锁定ROWS或COLUMNS。如果你打算随机地一次访问矩阵一个项目,我认为这应该做得很好:

public class CacheMatrix
{
    private MyType[][] cachedItems;

    public CacheMatrix(int size) {
        this.cachedItems = new MyType[size][size];
    }

    public MyType readItem(int x, int y) {
        synchronized (cachedItems[x]) {
            return cachedItems[x][y];
        }
    }

    public void storeItem(int x, int y, MyType item) {
        synchronized (cachedItems[x]) {
            this.cachedItems[x][y] = item;
        }
    }
}