2017-10-13 34 views
0

在進行多線程時,我一直在尋找線程安全性。我正在研究使用鎖來使自定義數據結構線程安全。在java中自定義數據結構線程安全嗎?

這是用於製作此自定義直方圖線程安全的最合適的實現嗎?

另外我是新來的。如果我想要幫助跟蹤代碼以找出它的作用,是否有我可以使用的標籤?

直方圖類(不安全)

public class Histogram 
{ 
    protected long[] bins; 
    protected int min, max, range; 
    protected int numBins; 

    public Histogram(int max, int min, int numBins) 
    { 
     this.max = max; 
     this.min = min; 
     this.numBins = numBins; 
     bins = new long[numBins]; 
     range = max - min + 1; 
    } 

    public void add(int num) 
    { 
     int bin = (int) Math.floor(((num - min) * 1.0/range) * numBins); 
     bins[bin]++; 
    } 

    public int absDifference(Histogram histogram) 
    { 
     int sum = 0; 
     if (histogram.min == min && histogram.max == max && histogram.numBins == numBins) 
      for (int i = 0; i < bins.length; i++) 
       sum += (int) Math.abs(bins[i] - histogram.bins[i]); 

     return sum; 
    } 

    @Override 
    public String toString() 
    { 
     String out = String.format("{Min: %d, Max: %d, # Bins: %d, Values: ", min, max, numBins); 
     for (int i = 0; i < bins.length; i++) 
      out += bins[i] + ", "; 

     out = out.substring(0, out.length() - 2); 
     out += "}"; 
     return out; 
    } 
} 

線程安全類的直方圖

import java.util.concurrent.locks.Lock; 
import java.util.concurrent.locks.ReentrantLock; 


public class HistogramSafe extends Histogram 
{ 
    private Lock[] binLocks; 

    public HistogramSafe(int max, int min, int numBins) 
    { 
     super(max, min, numBins); 

     binLocks = new ReentrantLock[numBins]; 
     for (int i = 0; i < numBins; i++) 
      binLocks[i] = new ReentrantLock(); 
    } 

    @Override 
    public void add(int num) 
    { 
     int bin = (int) Math.floor(((num - min) * 1.0/range) * numBins); 

     binLocks[bin].lock(); 
     bins[bin]++; 
     binLocks[bin].unlock(); 
    } 
} 
+0

如果用戶回答您的問題,請接受他的回答([接受答案:它是如何工作的?](https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-工作))。如果不是,那麼請說明還沒有答案,這是StackOverflow的重要組成部分,非常感謝。 – Zabuza

回答

1

這要看情況。如果您的numBins(也minmax)可變不能改變,即你的數據結構是固定大小的,那麼它應該是線程安全,允許不同的倉的平行修飾。


但如果numBins(或minmax)是可以修改的,然後它不是線程安全的了。正如您之前訪問numBins那麼這也是一個共享資源,並且它不在之內,相同的鎖

線程可能會進入方法,讀取numBins然後睡眠(由於線程調度程序)。現在另一個線程來執行完整的方法。舊線程繼續並設置bins[bin]++,但過期值numBins

如果,例如,還提供了remove功能,那麼這甚至有可能導致IndexOutOfBoundException以來的第一個線程可以讀取尺寸10,然後其他線程減少大小5。當第一個線程繼續時,它可能會嘗試寫入無效索引

1

爲了確保一種方法是線程安全的,​​關鍵字可以提供幫助。另外任何不可變的數據結構都是主要是線程安全。

public synchronized void methodName(){} 

Zabuza說,這將阻止所有試圖調用該方法的線程。

另一種方式保證線程安全是使synchronized塊將採取作爲參數上要進行鎖定

public void methodName(){ 
    synchronized(object) { 
    ... 
    } 
} 
+3

'synchronized',在這種情況下,會阻塞所有線程的整個方法。 OP試圖實現想要修改**不同bin的線程**可以繼續。 – Zabuza

1

您應該調查使用的AtomicInteger爲你的bin成員的對象。在你的例子中,線程安全問題是由於整數增加(讀取,添加,寫入)。 AtomicInteger操作是線程安全的,速度更快。

同步和鎖定更適合保護複雜的數據結構。

0

我會從不同的角度來看待這個 - 不,在我看來,它不是線程安全的。爲什麼?因爲你允許繼承。當有人擴展這個類時,很多事情可能會出錯 - 主要是覆蓋add方法。