2016-11-29 93 views
0

說我有一個服務器與多個線程共享一個數據實例的引用。快速例如,同步方法vs ReentrantLock

EDIT1:更新了可讀性

public void main() { 
Data data = new Data(); 
ReentrantLock rl = new ReentrantLock(true); 
ReadThread t1 = new ReadThread(data, rl); 
UploadThread t2 = new UploadThread(data, rl); 
t1.start(); t2.start(); 
} 

class ReadThread extends Thread { 
private Data data; 
private ReentrantLock lock; 

ReadThread(Data d, ReentrantLock l){ data = d; lock = l; } 

    void run(){ 
     lock.lock(); 
     try{ 
     data.put(aString) 
     } finally { lock.unlock(); } 
    } 
} 

class UploadThread extends Thread { 
private Data data; 
private ReentrantLock lock; 

UploadThread(Data d, ReentrantLock l){ data = d; lock = l; } 

    void run(){ 
     lock.lock(); 
     try{ 
     data.put(aString) 
     } finally { lock.unlock(); } 
    } 
} 

是更好地使用鎖像上面,或同步像下面的put方法,

class Data { 
private LinkedList<String> data = new LinkedList<String>(); 
synchronized void put(String x){ data.add(x); } 
} 

這是相當粗糙,

我大多隻關心併發性。

使用同步方法我是否正確地假設在類的「Data」實例/對象上會發生同步?因此一個UploadThread可以調用put過程/方法,一個ReadThread可以並行執行相同的操作。然而,使用ReentrantLock示例,只有一個線程可以在任何時候執行put電話嗎?

如果在「數據」類中,我將LinkedList設置爲靜態,並且使put方法同步且靜態,會發生什麼?哪種方法最好?如果我將事物變爲靜態,我是否會失去mut?

+5

您正在使用'Lock'錯誤。鑑於此,使用'synchronized'。或閱讀更多。多得多。 –

+2

另外,不要'擴展線程'。 –

+1

另外,格式化您的代碼。請。這幾乎是難以辨認的。 –

回答

2

在Java中​​部分是可重入的。這意味着單個線程可以根據需要多次進入同步部分,但只有在沒有其他線程存在時才能進入新線程。當前在這些部分中的線程已經獲得一個鎖,並且僅在離開所有同步部分時才返回鎖。除了通過方法簽名來聲明​​之外,​​也可以直接在對象上調用。例如;這兩種方法都會有同樣的效果:

synchronized public void foo() { 

} 

public void foo() { 
    synchronized(this) { 

    } 
} 

ReentrantLock是隻有一個線程非常相似,​​可以同時獲取鎖。如果一個線程到達lock.lock()語句,它將等待,直到鎖被另一個線程解鎖。如果線程已經鎖定,它將繼續。在單個同步代碼塊不夠用的更復雜情況下,這可能非常有用。

會發生什麼,如果...我使put方法同步和靜態?

如果方法是static synchronized這意味着您正在鎖定類本身而不是類的實例。它獨立於實例​​方法被鎖定。


爲您的代碼:

在這裏做最簡單的事情將是使Data對象轉換爲線程安全的對象。如果你不能編輯這個類的代碼,那麼一個有效的策略就是將這個對象包裝在一個線程安全的包裝器中。

interface Foo { 
    void bar(); 
} 
class UnsafeFoo implements Foo { 
    @Override bar() { ... } 
} 
class ThreadSafeFoo implements Foo { 
    Foo foo; 
    ThreadSafeFoo(Foo foo) { this.foo = foo; } 
    @Override synchronized bar() { foo.bar(); } 
} 

Foo unsafe = new UnsafeFoo(); 
Foo safe = new ThreadSafeFoo(unsafe); 
+1

謝謝你關於'static synchronized'的回答,因爲我在做什麼我可以編輯這個類,這樣應該沒問題。欣賞它:) – I2obiN