即使对同步方法的访问,int也会增加两次

时间:2014-03-31 07:40:44

标签: java multithreading

我在同步的方法中增加一个int OBECNA_LICZBA。所以只有一个线程可以增加它,并且它应该增加一个。但它有时会增加3.为什么OBECNA_LICZBA增加的次数增加1?

文件输出:

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

    }

}

1 个答案:

答案 0 :(得分:3)

pobierzObecneHaslo()循环内有两次while调用,只有一个调用输出

bw.write(hasloDoSprawdzenia);

因此,似乎即使您只假设一个线程,您的值也会在打印之间增加2,这似乎是当前的行为。

此外,您的代码当前结构的方式,您可以防止多个线程同时递增变量,但是您不会阻止多个线程在您读取值和调用时间之间运行

bw.write(hasloDoSprawdzenia);

如果您有多个线程,那么您也可能遇到无序打印的问题。