java - 即使在同步方法中访问 int,int 也会递增两次

标签 java multithreading

I 在同步方法中递增 int OBECNA_LICZBA。因此只有一个线程可以增加它,因此它应该增加 1。但有时会增加 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();
            }
        }

    }

}

最佳答案

while 循环中对 pobierzObecneHaslo() 进行了两次调用,其中只有一次通过调用写入输出

bw.write(hasloDoSprawdzenia);

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

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

bw.write(hasloDoSprawdzenia);

因此,如果您有多个线程,您也可能会遇到乱序打印的问题。

关于java - 即使在同步方法中访问 int,int 也会递增两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22755997/

相关文章:

java - 如何从 setOnItemSelectedListener 方法获取字符串?

java - 散列和索引列表或数组?

c++ - static const char [] 在类线程安全吗?

java - 如何停止 ExecutorService 上所有已提交的任务

multithreading - 当我在kubernetes中使用1000m以下的CPU请求时,同一容器中的多个线程可以同时使用多个内核并行运行吗?

java - 如何在 BaseClass 复制构造函数中复制 SubClass 对象

java - Eclipse PDE 中的日志记录策略

c# - 将 ThreadPool 与回调一起使用

applet - 如何为浏览器小程序指定特定的 JRE?

java - android 致命异常 : AsyncTask #2