Ir ao conteúdo

Posts recomendados

Postado

Bom dia, estou tentando representar um exercício simples para trabalhar com Threads em Java, hoje tentei implementar um programa que cria 4 Threads e cada uma acessa uma variável compartilhada que faz o incremento da mesma, a intenção é evitar que mais de uma thread acesse essa variável ao mesmo tempo usando a palavra reservada synchronized. Porém quando executo meu código varias vezes, há algumas situações que aparentemente mais de uma thread é acessada ao mesmo tempo. Por exemplo:

 

saída recebida:

Thread-3 2

Thread-0 1

Thread-1 2

Thread-2 3

 

pois a saída esperada era:

Thread-3 0

Thread-0 1

Thread-1 2

Thread-2 3

 

Não necessariamente nessa ordem de thread, mas obrigatoriamente os números em negrito devem ser únicos.

 

Gostaria de saber porque a palavra reservada synchronized não está surtindo efeito, e o código está executando como se não a tivesse.

 

Segue o código do programa:

 

 

Class ThreadRunnable.java:


package com.threads.implementacao;

import java.util.logging.Level;
import java.util.logging.Logger;

public class ThreadRunnable implements Runnable {

    private String nome;
    private int tempo;
    public static int i = -1;

    public ThreadRunnable(String nome, int tempo) {
        this.nome = nome;
        this.tempo = tempo;

        Thread t = new Thread(this); 
        t.start();
    }

    @Override
    public synchronized void run() {

        i++;
        System.out.println(Thread.currentThread().getName() + ":" + i);
        
        
    }

}

 

Class ThreadExecute.java:


package com.threads.implementacao;

public class ThreadExecute {

    public static void main(String[] args) {
        ThreadRunnable thread1 = new ThreadRunnable("#0", 500);
        ThreadRunnable thread2 = new ThreadRunnable("#1", 500);
        ThreadRunnable thread3 = new ThreadRunnable("#2", 500);
        ThreadRunnable thread4 = new ThreadRunnable("#3", 500);

        
        System.out.println(Thread.currentThread().getName());
    }

}

 

Postado

Muito estranho, aqui funcionou corretamente em todas as vezes que eu executei. Segue as implementações que eu fiz:

package code;

public class OriginalRunnable implements Runnable {

    public static int i = -1;

    private String nome;
    private int    tempo;

    public OriginalRunnable(String nome, int tempo) {
        this.nome  = nome;
        this.tempo = tempo;

        Thread t = new Thread(this);
        t.start();
    }

    @Override
    public synchronized void run() {
        i++;
        System.out.println(Thread.currentThread().getName() + ":" + i);
    }
}

 

package code;

public class MyRunnable implements Runnable {

    private static int counter = -1;

    @Override
    synchronized public void run() {
        ++counter;
        System.out.println(Thread.currentThread().getName() + " " + counter);
    }
}

 

package code;

public class Main {

    public static void main(String[] args) {
        myImplementationWithObject();
        myImplementationWithoutObject();
        originalImplementation();
    }

    private static void myImplementationWithObject() {
        Runnable runnable = new MyRunnable();

        new Thread(runnable, "Thread 0").start();
        new Thread(runnable, "Thread 1").start();
        new Thread(runnable, "Thread 2").start();
        new Thread(runnable, "Thread 3").start();
    }

    private static void myImplementationWithoutObject() {
        new Thread(new MyRunnable(), "Thread 0").start();
        new Thread(new MyRunnable(), "Thread 1").start();
        new Thread(new MyRunnable(), "Thread 2").start();
        new Thread(new MyRunnable(), "Thread 3").start();
    }

    private static void originalImplementation() {
        OriginalRunnable r1 = new OriginalRunnable("Thread #1", 500);
        OriginalRunnable r2 = new OriginalRunnable("Thread #2", 500);
        OriginalRunnable r3 = new OriginalRunnable("Thread #3", 500);
        OriginalRunnable r4 = new OriginalRunnable("Thread #4", 500);
    }
}

 

Postado

@AdrianoSiqueira Agradeço a ajuda, entendi agora que o quando uso synchronized no método ele sincroniza a instancia do respectivo objeto, no caso da minha aplicação há uma variável estática que pertence a classe e não à instancia, nesse caso eu precisaria sincroniza-la na classe e não no método, da seguinte forma:

    public void run() {
        synchronized (ThreadRunnable.class) {
           i++;
           System.out.println(Thread.currentThread().getName() + ":->" + i);
        }
    }

 

  • Curtir 1
Postado

É um jeito de fazer, mas sincronizar a classe toda pode causar gargalos, se duas threads tentarem acessar recursos diferentes que em teoria não teria problema, apenas uma vai poder acessar porque a classe foi bloqueada. Talvez sincronizando apenas a variável i possa dar um resultado melhor.

Postado

Um jeito de fazer, é usando um objeto atômico:

import java.util.concurrent.atomic.AtomicInteger;

public class App {

    public static void main(String[] args) {
        for (int i = 1; i <= 5; i++) {
            new Thread(new MyRunnableSynchronized(), "Thread-" + i).start();
            //new Thread(new MyRunnable(), "T-" + i).start();
        }
    }


    private static class MyRunnable implements Runnable {

        private static AtomicInteger objetoAtomico = new AtomicInteger(0);

        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + ": " + objetoAtomico.get());
            objetoAtomico.set(objetoAtomico.get() + 1);
        }
    }

    private static class MyRunnableSynchronized implements Runnable {

        private static AtomicInteger objetoAtomico = new AtomicInteger(0);

        @Override
        public void run() {
            synchronized(objetoAtomico) {
                System.out.println(Thread.currentThread().getName() + ": " + objetoAtomico.get());
                objetoAtomico.set(objetoAtomico.get() + 1);
            }
        }
    }
}

 

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...