【问题标题】:Synchronized Cache Matrix同步缓存矩阵
【发布时间】:2013-05-28 21:15:17
【问题描述】:

我正在为学校开发一个 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),你能找到一个更好的方法,几乎​​只保留最小互斥但使用更少的锁吗?

感谢您的支持!

【问题讨论】:

    标签: java multithreading caching mutual-exclusion


    【解决方案1】:

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

    基本上,会创建一个持有mylockscount = min(concurrencylevel, size) 锁的内部数组。 每当发生读/写操作时,您都会锁定例如mylocks[somehashfunction(x, y) % mylockscount].

    这样,锁的数量应该只随着并发线程的数量而不是矩阵的大小而变化。

    【讨论】:

    • 这还不错,所以在您的示例中,“mylockscount”的一个好的值可能是线程数?
    • @Michele:基本上,是的 - 但让“concurrencylevel”成为(预期的)线程数,因此您可以将“mylockscount”初始化为“size”或预期线程数 - 以两者为准更小。
    • @Michele: ...和“somehashfunction”可能是一个简单的“xor”,如果你不想过度... :-)
    【解决方案2】:

    只是让访问方法同步有什么用?

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

    【讨论】:

      【解决方案3】:

      另一种选择是将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

      【讨论】:

        【解决方案4】:

        想到两种可能的情况:

        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;
                }
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-02-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-06-09
          • 1970-01-01
          • 2021-01-11
          • 2021-11-29
          相关资源
          最近更新 更多