2013-05-28 47 views
0

我正在爲一個學校的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)?

感謝您的支持!

回答

1

您可以考慮以減少鎖的數量,仍然保持性能實現lock striping

基本上,創建了一個持有mylockscount = min(concurrencylevel, size)鎖的內部陣列。 每當發生讀/寫操作時,您都會鎖定例如mylocks[somehashfunction(x, y) % mylockscount]

這樣,鎖的數量應該只與併發線程的數量成比例,而不是矩陣的大小。

+0

這是不壞的,所以在你的例子中,「mylockscount」的好價值可能是線程的數量? –

+0

@Michele:基本上,是的 - 但是讓「concurrencylevel」成爲(預期的)線程數,因此您可以將「mylockscount」初始化爲「大小」或預期線程數 - 以較小者爲準。 –

+0

@Michele:...和「somehashfunction」可能是一個簡單的「xor」,如果你不想過頭的話...... :-) –

0

另一種選擇是用AtomicReference<MyType>[][]代替MyType[][];在這種情況下,void storeItem將變爲boolean storeItem(int x, int y, MyType oldValue, MyType newValue),如果oldValue不等於當前保存在[x][y](在您要撥打AtomicReference#compareAndSet(oldValue, newValue)的表面下)的值,則返回false。這種方式你沒有任何鎖,你只需要實施重試邏輯,以防storeItem返回假

如果MyType是原始的,例如, int,然後使用適當的原子基元,例如AtomicInteger而不是AtomicReference

0

什麼是關於只是使訪問方法同步?

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

我想避免純監視器的方法,我不想序列化的讀者... –

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