2011-02-28 45 views
0

由於共享代碼,我面臨着與多線程相關的一個問題。我想避免同步。我看到了許多與AtomicInteger相關的線程信號量。但是,對於何種方式以及如何更好地選擇比同步更好的選擇還沒有清楚的認識。如何避免在多線程環境中同步?

這是我想讓線程安全的簡單代碼。 創建線程的類。

public class ThreadCheck implements Runnable { 
TestStaticVar var = new TestStaticVar(); 
@Override 
public void run() { 
    // TODO Auto-generated method stub 
    try { 
     var.holdOn(); 
    } catch (InterruptedException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

public static void main(String args[]) { 
    ThreadCheck t = new ThreadCheck(); 
    Thread t1 = new Thread(t); 
    Thread t2 = new Thread(t); 
    t1.setName("A"); 
    t1.start(); 
    t2.setName("B"); 
    t2.start(); 
}} 

要由多個線程執行的類。

public class TestStaticVar { 
Semaphore sem = new Semaphore(1); 
public void holdOn() throws InterruptedException{ 
    sem.acquire(); 

    System.out.println("Inside Hold on....."+Thread.currentThread().getName()+"==> ");//+i.get()); 
    try { 
      for (long i=0; i<Integer.MAX_VALUE; i++) { 

     } 
     System.out.println(var1.toString()); 
    } catch (Exception e) { 
    // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    System.out.println("Finished Hold on===="+Thread.currentThread().getName()); 
       sem.release(1); 
    System.out.println("Execution Completed by =====> "+Thread.currentThread().getName()); 
}} 

任何幫助是非常appriciate。

感謝, 拉傑什

+3

使用'Semaphore'無法幫助您避免同步,因爲它只是另一個同步原語。嘗試描述你的任務。 – axtavt

+0

使用內置的併發數據結構,或者只保留關鍵部分小。比寫一些不明顯線程安全的瘋狂代碼更好。 – ide

+0

這只是與實際代碼等效的示例代碼。我不能使用同步,我不能使對象不可變。有沒有其他方法可以實現與同步功能相同的功能? – RajeshS

回答

0

試圖避免同步塊的兩個主要原因是性能和保護自己免受死鎖的影響。

使用synchronize關鍵字涉及設置鎖定和保護同步操作的性能開銷。雖然調用synchronized塊會有性能損失,但當JVM需要管理該塊的資源爭用時,會有更大的衝擊。

java.util.concurrent.atomic中的類可以使用機器級原子指令而不是鎖定,使它們比使用鎖的代碼快得多。有關如何工作的更多信息,請參閱javadoc for the package

另外,正如u3050所提到的,避免可變共享狀態可以很大程度上防止同步。

+0

對不起,未格式化的代碼...我是新的堆棧溢出... AtomicInteger i = new AtomicInteger(0); public void holdOn()throws InterruptedException {if(i.compareAndSet(0,1)){System.out.println(「Inside Hold on .....」+ Thread.currentThread()。getName()+「== >「); // + i.get());嘗試{for(long i = 0; i RajeshS

+0

使用'incrementAndGet',而不是'++'。我沒有看到'compareAndSet'調用的需要。 –

+0

我想'我++'是'for循環'的計數器,我的代碼應該從'if block'線程安全。您能否詳細解釋incrementAndGet以及它如何有助於避免多重訪問? – RajeshS

4

的一種方式,以避免同步是讓每一個資源不可變這將被多個線程訪問。讓類/對象不可變確保它的線程安全。

1

如何根據情況避免同步。由於你的情況是有限的,並且沒有做任何需要鎖定的事情,所以最簡單的方法就是取消鎖定,即只在需要時鎖定。 (也刪除不做任何事情的長循環)然後你的應用程序運行得更快。

+0

這只是與實際代碼等效的示例代碼。長循環可以是任何東西。在我的情況下,其對遠程服務器和響應的數據庫調用可能因網絡流量而異。有沒有其他方法可以實現與同步功能相同的功能? – RajeshS

+0

有很多方法可以避免鎖定,但它們取決於你在做什麼。如果您正在等待數據庫,您爲什麼要鎖定?你的數據庫不支持鎖定/事務性? –

+0

BTW:訪問數據庫的成本很可能是同步的10,000倍。除非你可以消除對數據庫的訪問,否則我不會看到刪除同步。 –