2014-03-31 59 views
0

I在同步的方法中增加int OBECNA_LICZBA。所以只有一個線程可以遞增,並且應該遞增1。但它有時會增加3.爲什麼OBECNA_LICZBA增加了1?即使以同步方法訪問它,int也會增加兩次

輸出文件:

AB000024 
AB000026 
AB000028 
AB000030 
AB000032 
AB000034 
AB000036 
AB000038 
AB000040 
AB000042 
AB000044 
AB000046 
AB000048 
AB000050 
AB000052 
AB000054 
AB000056 
AB000058 

import java.io.BufferedWriter; 
import java.io.FileWriter; 
import java.util.LinkedList; 

import javax.swing.JOptionPane; 

public class B implements Runnable { 
    private static ZasobZamkniety ZASOB; 
    private static LinkedList<Pracownik> LISTA; 
    private static String OBECNE_INICJALY; 
    private static volatile boolean NIE_ZLAMANY = true; 
    private static volatile int OBECNA_LICZBA = 0; 
    private final static int MIN = 0, MAX = 999999; 
    private static BufferedWriter bw = null; 

    public static void fabrykaWatkow(int ileWatkow, ZasobZamkniety zasob, LinkedList<Pracownik> listaPracownikow) { 
     ZASOB = zasob; 
     LISTA = listaPracownikow; 
     OBECNE_INICJALY = listaPracownikow.get(0).getInijcaly(); 
     try { 
      bw = new BufferedWriter(new FileWriter("plik.txt")); 
     } catch (Exception e) { 
      // TODO: handle exception 
     } 
     for (int i = 0; i < ileWatkow; i++) 
      new Thread(new B()).start(); 
    } 

    private B() { 
    } 

    public static synchronized int getObecnaLiczba(){ 
     return OBECNA_LICZBA; 
    } 
    public static synchronized String pobierzObecneHaslo() {  
     String kombinacja = getObecnaLiczba() + ""; 
     while (kombinacja.length() < 6) 
      kombinacja = '0' + kombinacja; 
     String haslo = OBECNE_INICJALY + kombinacja; 
     przewin(); 
     return haslo; 
    } 

    public static synchronized void przewin(){ 
     OBECNA_LICZBA++; 
     if (OBECNA_LICZBA > MAX && LISTA.size() > 1) { 
      OBECNA_LICZBA = MIN; 
      LISTA.remove(); 
      OBECNE_INICJALY = LISTA.element().getInijcaly();   
     } 
    } 

    public synchronized static void setNieZlamany(boolean wrt){ 
     NIE_ZLAMANY = wrt; 
    } 
    public static boolean getNieZlamany(){ 
     return NIE_ZLAMANY; 
    } 

    public synchronized String odpytajZasob(String hasloDoSprawdzenia){ 
     return ZASOB.getTresc(hasloDoSprawdzenia); 
    } 
    @Override 
    public void run() { 
     while (getNieZlamany()) { 
      String hasloDoSprawdzenia = pobierzObecneHaslo();  
      try { 
       bw.write(hasloDoSprawdzenia); 
       bw.newLine(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
      String odpowiedz = odpytajZasob(hasloDoSprawdzenia); 
      if (!odpowiedz.equals(ZasobZamkniety.ZLE_HASLO)) { 
       setNieZlamany(false); 
       JOptionPane.showConfirmDialog(null, odpowiedz, "ZLAMANO HASLO", JOptionPane.PLAIN_MESSAGE); 
       JOptionPane.showConfirmDialog(null, odpowiedz, "Czas lamania" + (System.currentTimeMillis() - Test.START), JOptionPane.PLAIN_MESSAGE); 
      } else { 
       pobierzObecneHaslo(); 
      } 
     } 

    } 

} 
+2

通常使用'ALL_CAPS_NAMES'來引用'static final'成員。在可變狀態下使用它們會使讀者感到困惑 – Eric

+0

當您在代碼中使用許多非英文術語時,很難理解代碼應該做什麼。此外,請儘量遵守Java代碼約定(http://www.oracle.com/technetwork/java/codeconv-138413.html) - 這使您的代碼更易於閱讀。最後但並非最不重要的是:你的主要方法在哪裏?你創建了多少個線程?他們有沒有共同的目標? – Christian

回答

3

你有兩個呼叫pobierzObecneHaslo()while循環中,只有其中一人通過調用

bw.write(hasloDoSprawdzenia); 

這樣寫道輸出,看起來即使你只假設一個線程,你的值也會增加2之間的印刷品,這似乎是當前的行爲。

此外,您的代碼當前的結構方式,可以防止多個線程同時增加變量,但是您不會阻止多個線程在讀取值和時間之間運行

bw.write(hasloDoSprawdzenia); 

因此,如果您有多個線程,您也可能會遇到無序打印的問題。

相關問題