Synchronized

19 respostas
F

gaçera nao consigo sinchronizar este codigo!Como faço?

import java.io.*;
import static java.lang.System.out;
class Conta_Corrente{
    private  float dinheiro=1000;  
    
   public synchronized void Saque(float y){
                 if(isSaldo()){
                   dinheiro-=y;    
                   out.println(" Foi possivel sacar meu amigo/a "+ Thread.currentThread().getName() + getSaldo());
                  }else{
                   out.println(" Nao possivel sacar meu amigo/a"+Thread.currentThread().getName()+ getSaldo());
                  }
     }
     public synchronized boolean isSaldo(){
      boolean b=dinheiro>0?true:false;
      return b;
     }
     public   synchronized float getSaldo(){return dinheiro;}
}  
     
public class Main extends Thread{
 Conta_Corrente c=new Conta_Corrente();
   public  void run() {
      synchronized(this){
       for(int i=0;i < 5; i++){
           c.Saque(340);
             
       }
      }
   } 
       
       
       
   
   
   
public static void main(String[] args) throws Exception{
       Main m=new Main();
       m.setName("fabio");
       m.start();
       m.join();
       Main m2=new Main();
       m2.setName("Ariel");
       m2.start();
      }
 }

19 Respostas

marciocamurati

Cara, não entendi oque você quis dizer com sincronizar o código ?

De qualquer forma olhando ele, imaginei que você queria que o dinheiro que inicia em 1000 seja sacado pelo Fábio e Ariel um de cada vez até seu saldo ser zerado, é isso?

Se for na lógica que você usou o atributo dinheiro pertence a cada classe instanciada no caso você instancia uma para:

- Fábio: dinheiro = 1000
 - Arial: dinheiro = 1000

Se na class Conta_Corrente:

class Conta_Corrente{  
     private static float dinheiro=1000;  
    ...
}

Ai sim o dinheiro seria compartilhado entre Fábio e Ariel, tendo os saques e verificação de saldos sequenciais até o final do saldo.

[]s

LPJava

qdo vc coloca o modificador synchronized vc acabou de sincronizar o metodo ou bloco do codigo!! seja mais claro na sua duvida!

F

blz,o metodo sincronizado nao deveria fazer com que as thrads acessem o metodo uma de casa vez??Para Fazer que não haja inconsistência de dados foi isso que fiz.Logo ja que os metodos estao sincronizado deveria ser impossivel que ou fabio ou ariel conseguisse sacar dinheiro ao mesmo tempo nao é??Mas nesse código isso nao acontece,as vezes mesmo com todos os metodos sincronizados fabio saca os ultimos 340 reais e depois logo em seguida Ariel tambem o faz!!fazendo que o saldo seja negativo,acho que agora ficou claro :wink:

F

kade vc LPJava??

fabim

A conta fica negativa, mas nao pq o synchronized nao funciona, mas sim pq sua logica esta errada.

Perceba que vc tem um saldo inicial de 1000, e após 2 saques restam 320. ( 1000 - (2*340) )

Como a sua logica é apenas verificar se o dinheiro em caixa esta positivo ( > 0 ), ele faz um saque de
340. Como 340 é maior do que o saldo ( 320 ) sua conta fica negativa.

Se sempre faz saques de 340, sua condicao deveria ser “dinheiro maior ou igual que 340”.

F

è verdade cara esqueci na Logica de programacao!! :oops:
obrigado!!

LPJava

se as duas threads tiver o mesmo destino sim :smiley: caso contrario os bloqueios sao diferentes lembra?

ViniGodoy

É o que o LP Java falou…

Você tem duas classes main, e duas classes conta corrente… E uma thread em cada conta corrente.
Então, cada thread pode, ao mesmo tempo, acessar a sua própria conta corrente, em paralelo! Sem problemas de sincronização, afinal, não há compartilhamento de objetos.

Seria um tanto estranho se o banco proibisse eu de sacar da minha conta, enquanto o LPJava saca da dele, concorda? É mais ou menos o que acontece em sua aplicação.

Para haver sincronização, você teria que ter duas threads no synchronized do mesmo objeto.

Acho melhor você relembrar esse tópico:
http://www.guj.com.br/posts/list/78631.java#416578

Onde já te expliquei isso, lembra?

No caso do seu código, faça a classe Main() receber uma ContaCorrente por parâmetro. Depois, crie apenas 1 conta corrente e use-a para os dois Mains criados. Você vai obter o resultado que espera. Nesse caso Fabio e Ariel terão uma conta conjunta, e estarão sacando da mesma conta.

F

Ola LPava!Desculpas a incomodacao cara ,mas nao consigo ainda entedender!!Fiz as alteracoes deacordo com as explicacoes de vcs!,mas nao consigo ainda obter o resultado esperado ou seja 2 theads acessando a
mesma conta nesse codigo

package javaapplication59;

import java.io.*;   
import static java.lang.System.out;   
class Conta_Corrente{   
    private  float dinheiro=1000;     
       
   public  void Saque(float y){   
                 if(isSaldo(y)){   
                   dinheiro-=y;       
                   out.println(" Foi possivel sacar meu amigo/a   " + Thread.currentThread().getName() + getSaldo());   
                  }else{   
                   out.println(" Nao possivel sacar meu amigo/a  "  +  Thread.currentThread().getName()  + getSaldo());   
                  }   
     }   
     public  boolean isSaldo(float y){   
      boolean b=dinheiro >0 && dinheiro > y? true :false;   
      return b;   
     }   
     public  float getSaldo(){return dinheiro;}   
}     
class OperacaoBancaria implements Runnable{   
   Conta_Corrente conta;
   OperacaoBancaria(Conta_Corrente c){
    conta=c;
  }
   public  void run() {   
     
       for(int i=0;i < 100; i++){   
           conta.Saque(300);   
               
   
      }   
   }   
}       
public class Main{   
     
public static void main(String[] args) throws Exception{
    
       Conta_Corrente c=new Conta_Corrente();//um objeto conta corrente 
       OperacaoBancaria operacao=new OperacaoBancaria(c);//somente uma conta corrente  
       Thread t=new Thread(operacao);//primeiro processo
       t.setName("Fabio");
       Thread t2=new Thread(operacao);//segundo processo
       t2.setName("Ariel");
       t.start();//inicializacao estado executavel
       t2.start();//inicializacao estado executavel
    //aqui nao sao dois threads diferentes acessando um memsmo object conta??
      }   
  }

De acordo com vc é Vinny eu criei um obejto ContaCorrente,assim 2 threads deveriam realmente accesar simultaneamente esse mesmo object pois o destino é mesmo mas isso nesse codigo nao acontece :frowning:

LPJava

fabioEM:
Ola LPava!Desculpas a incomodacao cara ,mas nao consigo ainda entedender!!Fiz as alteracoes deacordo com as explicacoes de vcs!,mas nao consigo ainda obter o resultado esperado ou seja 2 theads acessando a
mesma conta nesse codigo

package javaapplication59;

import java.io.*;   
import static java.lang.System.out;   
class Conta_Corrente{   
    private  float dinheiro=1000;     
       
   public  void Saque(float y){   
                 if(isSaldo(y)){   
                   dinheiro-=y;       
                   out.println(" Foi possivel sacar meu amigo/a   " + Thread.currentThread().getName() + getSaldo());   
                  }else{   
                   out.println(" Nao possivel sacar meu amigo/a  "  +  Thread.currentThread().getName()  + getSaldo());   
                  }   
     }   
     public  boolean isSaldo(float y){   
      boolean b=dinheiro >0 && dinheiro > y? true :false;   
      return b;   
     }   
     public  float getSaldo(){return dinheiro;}   
}     
class OperacaoBancaria implements Runnable{   
   Conta_Corrente conta;
   OperacaoBancaria(Conta_Corrente c){
    conta=c;
  }
   public  void run() {   
     
       for(int i=0;i < 100; i++){   
           conta.Saque(300);   
               
   
      }   
   }   
}       
public class Main{   
     
public static void main(String[] args) throws Exception{
    
       Conta_Corrente c=new Conta_Corrente();//um objeto conta corrente 
       OperacaoBancaria operacao=new OperacaoBancaria(c);//somente uma conta corrente  
       Thread t=new Thread(operacao);//primeiro processo
       t.setName("Fabio");
       Thread t2=new Thread(operacao);//segundo processo
       t2.setName("Ariel");
       t.start();//inicializacao estado executavel
       t2.start();//inicializacao estado executavel
    //aqui nao sao dois threads diferentes acessando um memsmo object conta??
      }   
  }

De acordo com vc é Vinny eu criei um obejto ContaCorrente,assim 2 threads deveriam realmente accesar simultaneamente esse mesmo object pois o destino é mesmo mas isso nesse codigo nao acontece :(

procurei o synchronized nao encontrei no seu codigo heeh! ou minha visao ja ta um caco… :smiley:

F

Nao cara ,eu quero que aconteca uma incosistencia de dados tipo,fabio saca
e fica 0 depois vem o processo Ariel que estava preste a sacar assim fica negativo :smiley:

LPJava

testa esse codigo cara… bem semelhante ao seu bem mesmo… e veja o problema do seu ai… nao está na thread no seu caso…

class caixa implements Runnable{
	
	double real=300.0;		
	public  void fluxo(double r){
		if(real <= 2000.0){
System.out.println("valor no caixa para " + Thread.currentThread().getName()+ " de " + real);
		try{
				Thread.sleep(500);
		}catch(InterruptedException e){}
		real +=r;
		System.out.println(Thread.currentThread().getName() + " depositou ");
		
		}else{
		System.out.println(Thread.currentThread().getName() + " caixa fechado");
		}		
	}
	public void run(){
		for(int x=0;x<4;x++){
			fluxo(300);		
	}
	System.out.println("total do caixa " +real);	}
	
	public static void main(String args[]){
		caixa c1 = new caixa();
			
			Thread maria = new Thread(c1);
			Thread jose = new Thread(c1);
				maria.setName("maria");
				jose.setName("jose");			
			maria.start();
			jose.start();
	}}

flw!

ViniGodoy

fabioEM:
Nao cara ,eu quero que aconteca uma incosistencia de dados tipo,fabio saca
e fica 0 depois vem o processo Ariel que estava preste a sacar assim fica negativo :D

Você deve, então, preparar o seu código para rodar milhares de vezes.
Se a inconsistência fosse fácil assim de achar, seria uma maravilha trabalhar com multi-threading…

Dica: Para fazer isso, faça com que uma das threads faça depósitos e outra saques. Faça quem saca tentar sacar R$500,00 e quem deposita depositar só R$300,00. Só deixe sacar se tiver saldo… E deixa o seu programa rodando…

Uma hora a inconsistência aparece, pode ter certeza!

F

ok vou tentar aqui valeu ! :smiley:

F

ViniGodoy:
fabioEM:
Nao cara ,eu quero que aconteca uma incosistencia de dados tipo,fabio saca
e fica 0 depois vem o processo Ariel que estava preste a sacar assim fica negativo :D

Você deve, então, preparar o seu código para rodar milhares de vezes.
Se a inconsistência fosse fácil assim de achar, seria uma maravilha trabalhar com multi-threading…

Dica: Para fazer isso, faça com que uma das threads faça depósitos e outra saques. Faça quem saca tentar sacar R$500,00 e quem deposita depositar só R$300,00. Só deixe sacar se tiver saldo… E deixa o seu programa rodando…

Uma hora a inconsistência aparece, pode ter certeza!

Era justamente isso cara,eu achavo que provar uma inconsistencia era trivial ja tinha tentado de tudo!valeu Vinny!!! :slight_smile:

F

ok nesse caso para nao dar problemas com o caixa a mais,seria suficiente alterar o if com

if(real+r <= 2000.0){}

e comentar

//try{
		//		Thread.sleep(500);
		//}catch(InterruptedException e){}

assim nao tem perigo que um processo passe a frente do outro ne?
valeu pela ajuda ai cara!!

F

ok Vinny se tiver um tempinho por favor gostaria que tu desse uma olhada nesse código.Peguei a idéia de alguém que postou um exemplo bem parecido.Temos uma loja com uma promoção;5 cellulares a venda,no entanto temos 11 clientes interessados na comprar as vezes qd roda acontece que 6 clientes compram cellulares ou seja mais do que esta no estoque.Poderia se dizer então que se obteve a incosistência de dados?

package javaapplication59;

  
import java.io.*;

import static java.lang.System.out;
import java.util.*;
class Cellular{
    String[] tipo=new String[]{"SONY-S21334","ERICSON E32230","MOTOROLA M567789","PORCARIAP02322"};
}
   
class Loja{
     int quantidade_total;
     Cellular cellular=new Cellular();
     static final int UNIDADEPRECO=300;
     Loja(int quantidade_total){
        this.quantidade_total=quantidade_total;
    }
    public boolean getQuantidade_total(){
       if(quantidade_total > 0)return true;
       else return false;
   }
    public  boolean  vender(int preço_ofertado){
      int mo=(int) (Math.random()  * cellular.tipo.length);
      String modelo=cellular.tipo[mo];
       if(getQuantidade_total()){//é ainda possivel vender
                            if(preço_ofertado == UNIDADEPRECO){
                                  try{
                               Thread.sleep(500);   
                              }catch(InterruptedException e){}
                            
                           }
        quantidade_total--; 
       return true;                     
      }else  
       out.println("Acabaram os celulares");
       return false; 
    }
  
}
    
class Comprador extends Thread{
    Loja loja;
   int oferta[]={250,300,100,350,170,320,310,134,211,302};
    Comprador(Loja loja){
        this.loja=loja;
    }
   int  oferta(){
        int y=(int)(Math.random() * oferta.length);       
       return oferta[y];  
    }
   
    public void run()  {
        for(int i=0;i<5;i++){
            int y=oferta();
            if(loja.vender(y)){//tenta comprar um dos cellulares
          out.println("O Senhor/a " +Thread.currentThread().getName()+ " comprou pelo preço de reais $:"+ y);
           break;
        
            }
            
        }
    }
  }
public class Main3{     
       
public static void main(String[] args){   
      Loja l=new Loja(5);

     Comprador[] arrayclientes=new Comprador[11];
         for(int i=0;i< arrayclientes.length;i++)
          arrayclientes[i]=new Comprador(l);
     
       arrayclientes[0].setName("Lois");
       arrayclientes[1].setName("Pedro");
       arrayclientes[2].setName("Paolo");
       arrayclientes[3].setName("Lucas");
       arrayclientes[4].setName("Ariel");
       arrayclientes[5].setName("maria");
       arrayclientes[6].setName("Tom");
       arrayclientes[7].setName("carlos");
       arrayclientes[8].setName("Just");
       arrayclientes[9].setName("Fredy");
       arrayclientes[10].setName("Norton");
      
      for(int i=0;i< arrayclientes.length;i++)
          arrayclientes[i].start();
      }
    
}
ViniGodoy

Claro!

Agora tente obter esse problema sincronizando os métodos publicos da loja…Você não vai conseguir.

F

ViniGodoy:
Claro!

Agora tente obter esse problema sincronizando os métodos publicos da loja…Você não vai conseguir.


È verdade mestre!!valeu!! :stuck_out_tongue:

Criado 29 de janeiro de 2008
Ultima resposta 1 de fev. de 2008
Respostas 19
Participantes 5