Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

146
Visualizações
Threads occasionally blocking while writing to the same file

I am trying to read from two text files (having the same number of lines, i.e. 10000) using two separate threads, one file containing Strings and the other containing Integers. Afterwards I want to write in another text file (String,Integer) values from corresponding positions in the result sets, each on a distinct line. For these purposes I'm using two classes implementing the Runnable interface.

The problem I'm facing is that every time I run the program, there is a chance that one of the threads is blocking execution, and I don't understand why considering that I'm using wait() and notify() in a synchronized block. More specifically, at times the program runs successfully finishing execution, while in most cases it stops at various stages (e.g. ~3000 out 10000 lines written, or even ~500).

citireInteger is a reference to the other thread which is reading the Integer file.

Here is relevant code from the classes dealing with reading from the String and Integer files, respectively:

@Override
public void run(){

    ........
    try {
        pw = new PrintWriter(new BufferedWriter(new FileWriter("rezultat.txt", true)));

        for(int i = 0; i < strings.size(); i++){

            synchronized(this){
                pw.write(strings.get(i));
            }

            synchronized(citireInteger){
                citireInteger.notifyAll();
            }

            try{
                synchronized(this){
                    wait();
                }
            } catch(InterruptedException e){
                e.printStackTrace();
            }
        }
    } catch(FileNotFoundException e){
        e.printStackTrace();
    } catch(IOException e){
        e.printStackTrace();
    } finally{
        pw.close();
    }

    synchronized(citireInteger){
        citireInteger.notify();
    }
}

The thread reading the Integer file:

    public void run(){

    ...........

    try{
        pw = new PrintWriter(new BufferedWriter(new FileWriter("rezultat.txt", true)));

        for(int i = 0; i < ints.size(); i++){

            synchronized(this){
                pw.write(ints.get(i) + '\n');
                System.out.println(ints.get(i));
            }
            synchronized(citireString){
                citireString.notifyAll();
            }

            try{
                synchronized(this){
                    wait();
                }
            } catch(InterruptedException e){
                e.printStackTrace();
            }
        }
    } catch(FileNotFoundException e){
        e.printStackTrace();
    } catch(IOException e){
        e.printStackTrace();
    } finally{
        pw.close();
    }

    synchronized(citireString){
        citireString.notify();
    }
}
over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

What's happening is that one thread is calling notifyAll on the other thread, then getting switched out before synchronizing on its own writer to call wait. The other thread does its write, synchronizes on its writer, and calls wait. Then the first thread gets switched in again, synchronizes on its writer, and calls wait. There's your deadlock.

Better would be to have both threads synchronize on the same object to write. Best would be to store the data in memory in a thread safe way and write from a single thread once reading from both threads was complete.

over 4 years ago · Santiago Trujillo Relatório

0

When you notify the other thread, the other thread will only see that when the other threads is waiting for it. I the other thread is outside that synchronized block, and enters that synchronized block after it is notified, it will then wait for a notify that won't happen, or rather, than happened before it started to wait for it. It's hard to really determine what the objective of this exercise is, but I'm guessing it is about two threads taking turns doing a write. Ok, so, how about making the synchronized(citireInt/String) block encompass its entire code! This way, the other thread trying to obtain a lock will ONLY get that lock WHEN the other thread is waiting. That I think would guarantee no blocking and the result would be both threads taking turns, one by one.

Edit: not entirely exactly as I described, but the key points is where to synchronize...

   public void run()
   {
       ...........

       try
       {
           pw = new PrintWriter(new BufferedWriter(new FileWriter("rezultat.txt", true)));

           synchronized(this)
           {
               for(int i = 0; i < ints.size(); i++)
               {
                   pw.write(ints.get(i) + '\n');
                   System.out.println(ints.get(i));

                   synchronized (citireString)
                   {
                       citireString.notifyAll();
                   }

                   try
                   {
                       wait();
                   }
                   catch (InterruptedException e)
                   {
                       e.printStackTrace();
                   }
               }
           }
       }
       catch (Throwable e)
       {
           e.printStackTrace();
       }
       finally
       {
           pw.close();
       }
    }
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda