Loading ...
Sorry, an error occurred while loading the content.

Re: [riojug] Como fazer um Pedido (shopping cart) totalmente thread-safe?

Expand Messages
  • Victor Hogemann
    Então, Essa pergunta não faz muito sentido, não? Já que não existe fork() em Java. Você vai até vários containers rodando no mesmo servidor, mas isso
    Message 1 of 43 , Jul 2 7:18 AM
    • 0 Attachment
      Então,

      Essa pergunta não faz muito sentido, não? Já que não existe fork() em Java.

      Você vai até vários containers rodando no mesmo servidor, mas isso é mais pra contornar o limite do tamanho máximo de memória em sistemas 32 bits, que é de 2GB. Então pra aproveitar toda a memória da máquina, você pode ter duas, três ou quatro JVMs executando ao mesmo tempo em servidores com mais de 4GB de RAM.

      [ ]s
      ----
      Victor Hogemann

      On Jul 2, 2009, at 10:57 AM, Vitor Fernandes wrote:



      Então o que seria mais performatico uma unica JVM trabalhando com threads nativas, ou multiplas JVMs? Sei que com multiplas JVMs o gerenciamento e muito mais custoso.

      2009/7/2 Victor Hogemann <victor.hogemann@ gmail.com>


      Vitor,


      Sobre threads nativas, ou kernel threads... A vantagem das threads nativas é que cada thread é mapeada 1:1 para uma entidade no scheduller do kernel, assim ele pode distribuir as threads livremente entre vários processadores. Quando você usa threads de usuário, as tais green threads do Java antes do 1.3, o esquema fica 1:N, ou seja você ainda tem processamento em paralelo, mas o scheduler só consegue alocar o processo inteiro, e não threads individuais, pra cada processador.

      Quanto a diferenças que você viu no seu teste em C entre thread e fork, cara... isso depende de muitas coisas. Entre elas o jeito que você implementou o programa, a biblioteca de threading que você usou, e o SO em que executou (por causa das políticas de schedulling) . A diferença prática, vou repetir, é que com thread você compartilha o mesmo segmento de memória, e com fork você tem um novo processo com um segmento de memória separado.

      [ ]s
      On Jul 2, 2009, at 9:31 AM, Vitor Fernandes wrote:




      Eu executo um programa simples em C com um loop que printa o contador no console bifurcando o mesmo com fork. Repare que ambos os fluxos executam ao mesmo tempo e as linhas de ouput ficam alternadas. É simultaneo.

      Já no mesmo caso fazendo uso de thread ele geralmente executa um fluxo por vez ou começa o outro fluxo bem depois do primeiro. Com thread nunca se sabe quando o código vai ser executado. Com java isso fica claro com o GC.

      Agora uma dúvida sobre as threads nativas. Eu tenho apenas a JVM disputando tempo de processador em um sistema que não usa threads nativas. Ao usar as mesmas eu tenho mais de um processo disputando tempo de processador. Ou seja mais chances de um processo ser executado. Ai estaria o ganho em desempenho?

      2009/7/2 Victor Hogemann <victor.hogemann@ gmail.com>


      Então,


      No Spring você pode definir o comportamento das instâncias dos beans criados pelo contexto. No caso singleton aí indica que o Spring vai criar apenas uma instância de determinado bean, ao contrario do escopo Prototype que cria uma instancia nova a cada acesso ao bean.

      O Singleton do Spring, portanto, não é o Design Pattern Singleton... Aliás o uso do DP Singleton com o Spring é desencorajado, já que o Spring passa por cima do construtor privado e instancia a classe ele mesmo! Façam o teste, criem uma classe usando o DP Singleton e declarem dois beans no Spring como se estivessem declarando qualquer outro bean... Você vai ver que vão existir DUAS instâncias desse bean na sua aplicação!


      [ ]s
      ----
      Victor Hogemann

      On Jul 2, 2009, at 6:15 AM, Bruno Pacheco Lopes da Silva wrote:




      Interessante, dessa eu não sabia, então isso explica o problema que eu tive ao rodar aquela aplicação citada anteriormente no Ubuntu, pois seria praticamente impossível que a JVM falhasse no escalonamento das threads.

      Vlw, brother.

      Ah, já ia me esquecendo, acabou passando e eu nem comentei, uma dúvida, Spring não é um framework, e Singleton não é um padrão de projeto? Qual seria a relação aqui? Até onde eu sei, no caso do singleton, para que este seja bem aplicado é o desenvolvedor quem deve torná-lo thread safe. Geralmente se utiliza para singleton o conceito de monitor para tratar a concorrência.
       
      Bruno Pacheco - Rio de Janeiro - BR



      From: Victor Hogemann <victor.hogemann@ gmail.com>
      To: riojug@yahoogroups. com
      Sent: Wednesday, July 1, 2009 11:20:53 PM
      Subject: Re: [riojug] Como fazer um Pedido (shopping cart) totalmente thread-safe?

      Bruno,


      Desde a versão 1.3 o Java utiliza system threads no Linux, então o controle das threads fica com o OS mesmo. Tanto que cada thread do Java aparece como um processo separado, já que as threads no Linux são implementadas como processos clonados.

      [ ]s
      ----
      Victor Hogemann

      On Jul 1, 2009, at 9:59 PM, Bruno Pacheco Lopes da Silva wrote:




      Esclarecemos algumas coisas.

      Em um processador com mais de um núcleo, o acesso a fila de processos realmente não é simultâneo, obviamente pois não posso ter o mesmo processo executando em mais de um núcleo. Mas não é aqui que se leva em consideração o paralelismo, mas sim na execução do processo.

      A ideia de ter múltiplos processadores é antiga e, como foi dito anteriormente, o Windows já carrega isso já a algum tempo, mesmo que de forma obscura para alguns. Só para citar um exemplo interessante, no semestre retrasado fiz uma pequena aplicação em java para demonstrar a ideia do uso de semáforos para tratar concorrência. Fiz testes em três SOs diferentes, Um Windows XP Pro, um FreeBSD 7.0 e um Ubuntu 8.04. Os dois primeiros executaram a aplicação conforme o planejado, já no Ubuntu algumas threads simplesmente morriam antes do esperado ou simplesmente não parava de executar. (Isso não ocorreu num Debian posteriormente testado, é claro XD). Enfim, neste caso o SO que apresentou o melhor escalonamento, da forma mais "justa", foi o Windows XP.

      Quanto ao Java, quem controla a execução das threads é a JVM, e não o SO, portanto, uma aplicação java, sem levarmos em consideração outros fatores, como multiplos servidores que atendem a uma determinada fila de requisição por exemplo, não é de fato multiprocessado, salvo aplicações que rodem em Solaris e seus derivados, neste cada thread é uma thread nativa.
       
      Bruno Pacheco - Rio de Janeiro - BR



      From: Vitor Fernandes <thevitu@gmail. com>
      To: riojug@yahoogroups. com
      Sent: Wednesday, July 1, 2009 8:46:57 PM
      Subject: Re: [riojug] Como fazer um Pedido (shopping cart) totalmente thread-safe?


      Victor,
       
      Por padrão Session Beans (Stateless) em Um container EJB sempre são thread safe.
      E o Scope default de um Bean no Spring e Singleton o que o torna  thread safe.
       
      Ate onde eu entendo do processo de escalonamento:
       
      Eu um processador de um único núcleo.
       
      Eu possuo uma unica fila de processos com N prioridades a serem executados. (Existem algoritimos que organizam a mesma)
      A cada clock tick do cpu um desses processos e atendido.
      Um novo processo somente ira ser atendido quando o processador estiver disponível.
       
      Eu um processador de um mais de um núcleo.
       
      Eu possuo uma fila de processos com N prioridades a serem executados. (Existem algoritimos que organizam a mesma)
      A cada clock tick do cpu um desses processos e atendido pelo nucleo que disponível.
      Um novo processo ira ser atendido imediatamente  enquanto existir um nucleo disponível.
       
      É mais rapido, mas ainda atende um por vez (não é simultaneo).
       
      Sistemas operacionais (como o unix que voce citou) realmente multiprocessados podem trabalhar e gerenciar mais de um processador e dedicar processadores para uma aplicação, como uma JVM. (É simultaneo multiplas threads da mesma aplicação sendo atendidas por processadores diferentes)
       
      Agora nunca vi SO da Microsoft rodando com hardware com mais de um processador.
       
      Em hardwares de alta criticidade onde  todos os componetes são dulplicados (processador, memoria, disco, etc...) todos os processos sofrem fork e rodam simultaneamente em processadores  distintos.
       
      2009/7/1 Victor Hogemann <victor.hogemann@ gmail.com>


      Vitor,


      A diferença entre Thread e Fork não é bem isso.

      Usando o fork você  cria uma nova  instância do  seu processo, uma cópia mesmo, com um segmento  de memória separado  e tudo mais. .. Se você precisa  coordenar  o que as instâ ncias do seu  aplicativo  estão fazendo,  tem que utilizar  alguma técnica  de IPC, já que  como eles nã o compartilham  o mesmo segmento  de memória nã o tem como utilizar  variáveis ou  objetos compartil hados pra fazer  esse controle.  Java não usa  Fork.

      Já utilizando Threads você cria um novo caminho de execução, dentro do mesmo processo. Ou seja, várias threads compartilham o mesmo segmento de memória, então elas podem ter acesso a variáveis e objetos compartilhados, sem precisar recorrer a IPC. Java usa Threads.

      Ao contrário do que você deve pensar, threads da mesma aplicação podem ser distribuidas a processadores diferentes em um sistema multi-processado. Tudo depende da implementação. Um jeito fácil de ver isso acontecendo é olhar qualquer container web rodando no Linux, as threads no Linux são implementadas por debaixo dos panos como processos clonados, então cada thread do Java aparece como um processo independente se você listar com o comando ps.

      http://java. sun.com/develope r/technicalArtic les/Programming/ linux/

      Essas são as diferenças básicas entre fork e threads. Se alguém te falou alguma coisa muito diferente disso, na boa, não sabia do que estava falando.

      Quanto a Monoprocessamento e Multiprocessamento. ..

      O Windows suporta vários processadores desde o NT 3.1, as versões que não suportavam vários processadores morreram com o Windows ME. Se foi a mesma pessoa que te explicou sobre fork e thread, já temos uma explicação para esse seu engano.

      [ ]s
      On Jul 1, 2009, at 12:24 PM, Vitor Fernandes wrote:



      Existe uma diferença em WebServer e Container. 
      Sobre o escalonada (spread):

      http://publib. boulder.ibm. com/infocenter/ wasinfo/v5r1/ /index.jsp? topic=/com. ibm.websphere. zseries.doc/ info/zseries/ ae/crun_wlm_ sessionplacement .html

      Paralelo (thread) e uma coisa, Simultaneo (fork) e outra. Isso fica bem claro quando voce programa em C.

      http://www.codeguru .com/forum/ showthread. php?t=413573

      Depende sim. Voce esta confundindo monoprocessamento com multiprocessamento: 

      http://www.google. com.br/search? hl=pt-BR&q=monoprocessamento +e+multiprocessa mento&btnG=Pesquisa+ Google&meta=&aq=7&oq=monopro

      Um S.O. monoprocessado como o windows por exemplo mesmo com um processador de multiplos núcleos vai continuar trabalhando como se tivesse somente um.

      Citei isso, porque vi tudo isso na graduação. Não estou inventando.

      Se colocar synchronized em tudo a performance do servidor já era.

      2009/6/30 Carlos Moscoso <moscoso.dev@ gmail.com>



      Com certeza pode haver concorrência no servidor. Na dúvida coloca synchronized em tudo!

      2009/6/30 Felipe Cypriano <fmcypriano@gmail. com>


      Não entendi, o que é requisição escalonada?

      Pelo que já li até hoje um sistema web, vou falar do básico sem frameworks. O servlet tem sim requisição (chamadas a métodos) simultânea. Para cada servlet o container mantém uma única instância dele e para cada HTTP request que recebe ele cria uma nova thread que acessa essa única instancia do servlet. Mesmo que tudo esteja no mesmo servidor e mesma JVM cada HTTP request é processado em paralelo, por isso o servlet deve ser thread-safe. Um exemplo de como eu acho que pode exisitr requisições simultâneas em único servidor.

      ---
      Felipe Cypriano


      2009/6/30 Vitor Fernandes <thevitu@gmail. com>



        Desculpe-me, mas requisições simultâneas somente podem existir em um sistema distribuido.
      Requisições a um único servidor são escalonadas.



      2009/6/30 Felipe Cypriano <fmcypriano@gmail. com>


      A sessão é compartilhada por usuário, ela pode responder a mais de uma requisição ao mesmo tempo normalmente. Por usuário é diferente de por chamada feita pelo usuário, o usuário pode abrir outra janela do navegador e continuará na mesma sessão enviando requisições simultâneas ao servidor.

      A chance de ocorrer acesso simultâneo em objeto compartilhado por sessão é menor do que em objetos a nível de aplicação (um servlet por exemplo, ou um spring bean singleton) mas ela existe.

      ---
      Felipe Cypriano


      2009/6/30 Carlos Moscoso <moscoso.dev@ gmail.com>



      Se o carrinho está na sessão não há necessidade de sincronizar porque não haverá acesso concorrente.  Se estiver tudo certo apenas o procedimento  de efetivar  a compra na sua aplicação precisa  ser controlado  por meio do  synchronized (ou transação de banco).


      2009/6/30 Felipe Cypriano <fmcypriano@gmail. com>



      Mas exatamente por estar na sessão que preciso que ele seja thread-safe, já que várias chamadas podem acesso-lo simultaneamente.

      A melhor solução é evitar a compra no último momento quando for persistir no banco, já que alguém poderia começar a fazer um pedido e parar o estoque ficaria errado pelo tempo que durar a sessão. Como dito pelo Rafael Cotta num email anterior.

      Para manter simples durante o momento de salvar o usuário não poderia modificar nada no pedido, é mais simples e fácil de dar manutenção do que implementar esse nível de sincronismo da lista.

      ---
      Felipe Cypriano


      2009/6/30 Felipe Gaúcho <fgaucho@gmail. com>


      O mais comum é colocar o carrinho na sessão do usuário :) e esquecer a
      concorrencia - visto que o carrinho é pequeno, contendo apenas a
      referência a meia dúzia de produtos..

      se o problema for evitar a compra de produtos que não estão no
      estoque, inclua no banco de dados uma flag para marcar produtos "na
      mão do cliente",... . pode ter um temporizador para evitar que o
      produto fique bloqueado muito tempo ou outro truque...

      2009/6/29 Carlos Moscoso <moscoso.dev@ gmail.com>:


      >
      >
      > Não vejo necessidade em sincronizar o acesso à lista de itens se você
      > concorda que eventual incosistência durante a navegação e processo de compra
      > é normal. Dito isso, o problema se resume a evitar que a compra de um item
      > que não existe seja efetivada. Considerando que na sua aplicação existe um
      > comando no caso de uso para confirmar a compra bastaria sincronizar este
      > metodo no seu código, que faz as ultimas validações.
      >
      > ps: Usar transações de banco para modelar esse problema pode comprometer o
      > design da sua aplicação uma vez que cada transação terá o escopo de uma
      > requisição apenas. Pra mim que considera uso de banco de dados relacional um
      > detalhe de implementação não me sentiria confortável nessa situação.
      >
      > 2009/6/29 Felipe Cypriano <fmcypriano@gmail. com>
      >>
      >>
      >> Olá Victor e Rafael,
      >>
      >> É extremamente importante que o estoque seja correto, e que nunca entre um
      >> pedido que deixe o estoque negativo. Basicamente esse é o requisito
      >> principal.
      >>
      >> Eu faço a validação tanto na view quanto na camada de serviço, enquanto o
      >> usuário esta adicionando itens ele ve o que está realmente disponível (não
      >> há "pré-baixa", só quando commita a transação que o estoque é alterado), na
      >> camada de serviço é verificado novamente se nenhum regra foi violada e se
      >> todos os itens estão em estoque, após isso tudo é salvo e commitado.
      >>
      >> Como o objeto de PedidoVenda é compartilhado por sessão eu o fiz como
      >> thread-safe, a única parte que não está 100% thread-safe (se eu não me
      >> engano) é a iteração sobre os itens.
      >>
      >> Eu pensei em proteger a referência em sessão quando o processo de "salvar"
      >> o pedido estivesse em andamento, isso traria thread-safe por confinamento,
      >> pois só o método de salvar tem acesso ao pedido e não mais o usuário atráves
      >> da sessão web. É o que vocês sugeriram ne?
      >>
      >> Outro jeito mais complexo seria ter um método dentro de PedidoVenda que
      >> execute uma chamada generica dentro do lock, por exemplo:
      >>
      >> public interface PedidoVendaIterator {
      >>     public PedidoVendaItem eachItem(PevidoVend aItem item);
      >> }
      >>
      >> public class PedidoVenda {
      >>     public void iterateItems( PedidoVendaItera tor iterator) {
      >>         synchronized (internalLock) {
      >>             for (PedidoVendaItem item : getItens()) {
      >>                     iterator.eachItem( item)
      >>             }
      >>         }
      >>     }
      >> }
      >>
      >> Ou seja, o pedido guardaria o lock e passaria o processamento a um
      >> command. Vocês veem algum problema com isso, além da complexidade?
      >>
      >> Alex, o livro é muito bom mas você vai ficar meio doido - igual a eu -
      >> pensando em concorrência, mas é bom que hoje em dia com cada vez mais
      >> núcleos nos processadores mais precisaremos saber sobre esse assunto.
      >>
      >> Abraços,
      >> ---
      >> Felipe Cypriano
      >>
      >>
      >> 2009/6/29 Rafael Cotta <rcotta@gmail. com>
      >>>
      >>>
      >>> Opa, Cypriano. A minha pergunta é: será que você realmente precisa de
      >>> mecanismos tão sofisticados para gerenciar esse carrinho de compras?
      >>>
      >>> Não sei quais são teus requisitos, mas imagino que os casos em que um
      >>> usuário coloque um ítem em um carrinho e na hora do checkout o ítem
      >>> não existe mais são mínimos. E mesmo assim, eu ficaria muito mais à
      >>> vontade de checar essa condição na hora de fechar a transação, ou
      >>> seja, registrar no banco o pedido, verificar o estoque e dar baixa no
      >>> estoque, no meu entendimento, deveria ficar em uma mesma transação de
      >>> banco.
      >>>
      >>> Caso alguma condição falhe, você pode fazer o tratamento adequado
      >>> (mostrar mensagem ao usuário) e dar rollback que tudo volta ao que era
      >>> antes.
      >>>
      >>> []s
      >>>
      >>> Rafael Cotta
      >>>
      >>> 2009/6/29 Alex Rios <alex.rios1337@ gmail.com>
      >>>
      >>> >
      >>> >
      >>> > Comprei esse livro a pouco tempo, apesar de ainda não poder ajudar vou
      >>> > acompanhar o tópico de perto, pois assunto também muito me interessa...
      >>> >
      >>> > 2009/6/29 Felipe Cypriano <fmcypriano@gmail. com>
      >>> >>
      >>> >>
      >>> >> Olá pessoal,
      >>> >>
      >>> >> Estou refazendo o site aqui da empresa, e desde a primeira versão (a
      >>> >> atual e minha primeira app web) eu já aprendi muita coisa, por isso estou
      >>> >> atualizando (refazendo praticamente) ele todo.
      >>> >>
      >>> >> A base que tenho sobre thread é o livro "Java Concurrency in Practice"
      >>> >> antes dele eu nem sabia prestar atenção nos problemas que acesso concorrente
      >>> >> poderia causar, e concorrencia em web é muito importante.
      >>> >>
      >>> >> O que estou em dúvida é como garantir thread-safe durante a iteração
      >>> >> sobre a lista de itens do pedido, eu estou usando um objeto privado como
      >>> >> lock de toda a classe pois o livro ensina que é melhor fazer para não expor
      >>> >> a "lógica" de thread-safe de sua classe, ou seja, não quebrar o
      >>> >> encapsulamento. Simplificando a classe é assim:
      >>> >>
      >>> >> public class PedidoVenda implements Serializable{
      >>> >>     private int id;
      >>> >>     private Integer numero;
      >>> >>     private Date dataEmissao;
      >>> >>
      >>> >>     private final Object internalLock = new Object(); // Esse é o lock
      >>> >>
      >>> >>     private final List<PedidoVendaItem> itens = new
      >>> >> ArrayList<PedidoVendaItem>();
      >>> >>
      >>> >>     // todos os getters and setters são sincronizados com internalLock
      >>> >>
      >>> >>     public List<PedidoVendaItem> getItens() {
      >>> >>         synchronized (internalLock) {
      >>> >>             return Collections. unmodifiableList (itens);
      >>> >>         }
      >>> >>     }
      >>> >>
      >>> >>     public PedidoVendaItem addItem(final PedidoVendaItem item) {
      >>> >>         if (item == null) {
      >>> >>             throw new IllegalArgumentExce ption("Item não pode ser
      >>> >> nulo.");
      >>> >>         }
      >>> >>
      >>> >>         item.setPedido( this); // PedidoVendaItem é thread-safe
      >>> >>         item.setNumero( proximoNumeroIte m());
      >>> >>         synchronized (internalLock) {
      >>> >>             itens.add(item) ;
      >>> >>         }
      >>> >>         return item;
      >>> >>     }
      >>> >> }
      >>> >>
      >>> >> O pedido fica na sessão web enquanto o usuário esta editando, ao
      >>> >> clicar em salvar a referencia desse pedido é passada à camada de serviço que
      >>> >> faz as validações e salva. Uma das partes da validação é verificar se todos
      >>> >> os itens do pedido estão em estoque, isso implica em percorrer a lista
      >>> >> retornada por getItens(), mas percorrer essa lista não garante que uma
      >>> >> chamada à addItem(item) ou removeItem(item) não será feita.
      >>> >>
      >>> >> A questão é como garantir que o objeto não será modificado durante a
      >>> >> validação?
      >>> >>
      >>> >> Se a explicação ficou confusa só me falar que explico melhor, ou pelo
      >>> >> menos tento.
      >>> >>
      >>> >> Abraços,
      >>> >> ---
      >>> >> Felipe Cypriano
      >>> >
      >>> >
      >>> >
      >>> > --
      >>> > Atenciosamente,
      >>> > Alex Rios - Programmer/Develope r
      >>> > GBS - GeoMidi Business Solutions
      >>> >
      >>> >
      >>
      >
      >
      >
      > --
      > Carlos Alexandre Moscoso
      > 

      -- 
      Looking for a client application for this service:
      http://fgaucho. dyndns.org: 8080/footprint- service/wadl





      -- 
      Carlos Alexandre Moscoso







      -- 
      Carlos Alexandre Moscoso

















    • Victor Hogemann
      Então, Essa pergunta não faz muito sentido, não? Já que não existe fork() em Java. Você vai até vários containers rodando no mesmo servidor, mas isso
      Message 43 of 43 , Jul 2 7:18 AM
      • 0 Attachment
        Então,

        Essa pergunta não faz muito sentido, não? Já que não existe fork() em Java.

        Você vai até vários containers rodando no mesmo servidor, mas isso é mais pra contornar o limite do tamanho máximo de memória em sistemas 32 bits, que é de 2GB. Então pra aproveitar toda a memória da máquina, você pode ter duas, três ou quatro JVMs executando ao mesmo tempo em servidores com mais de 4GB de RAM.

        [ ]s
        ----
        Victor Hogemann

        On Jul 2, 2009, at 10:57 AM, Vitor Fernandes wrote:



        Então o que seria mais performatico uma unica JVM trabalhando com threads nativas, ou multiplas JVMs? Sei que com multiplas JVMs o gerenciamento e muito mais custoso.

        2009/7/2 Victor Hogemann <victor.hogemann@ gmail.com>


        Vitor,


        Sobre threads nativas, ou kernel threads... A vantagem das threads nativas é que cada thread é mapeada 1:1 para uma entidade no scheduller do kernel, assim ele pode distribuir as threads livremente entre vários processadores. Quando você usa threads de usuário, as tais green threads do Java antes do 1.3, o esquema fica 1:N, ou seja você ainda tem processamento em paralelo, mas o scheduler só consegue alocar o processo inteiro, e não threads individuais, pra cada processador.

        Quanto a diferenças que você viu no seu teste em C entre thread e fork, cara... isso depende de muitas coisas. Entre elas o jeito que você implementou o programa, a biblioteca de threading que você usou, e o SO em que executou (por causa das políticas de schedulling) . A diferença prática, vou repetir, é que com thread você compartilha o mesmo segmento de memória, e com fork você tem um novo processo com um segmento de memória separado.

        [ ]s
        On Jul 2, 2009, at 9:31 AM, Vitor Fernandes wrote:




        Eu executo um programa simples em C com um loop que printa o contador no console bifurcando o mesmo com fork. Repare que ambos os fluxos executam ao mesmo tempo e as linhas de ouput ficam alternadas. É simultaneo.

        Já no mesmo caso fazendo uso de thread ele geralmente executa um fluxo por vez ou começa o outro fluxo bem depois do primeiro. Com thread nunca se sabe quando o código vai ser executado. Com java isso fica claro com o GC.

        Agora uma dúvida sobre as threads nativas. Eu tenho apenas a JVM disputando tempo de processador em um sistema que não usa threads nativas. Ao usar as mesmas eu tenho mais de um processo disputando tempo de processador. Ou seja mais chances de um processo ser executado. Ai estaria o ganho em desempenho?

        2009/7/2 Victor Hogemann <victor.hogemann@ gmail.com>


        Então,


        No Spring você pode definir o comportamento das instâncias dos beans criados pelo contexto. No caso singleton aí indica que o Spring vai criar apenas uma instância de determinado bean, ao contrario do escopo Prototype que cria uma instancia nova a cada acesso ao bean.

        O Singleton do Spring, portanto, não é o Design Pattern Singleton... Aliás o uso do DP Singleton com o Spring é desencorajado, já que o Spring passa por cima do construtor privado e instancia a classe ele mesmo! Façam o teste, criem uma classe usando o DP Singleton e declarem dois beans no Spring como se estivessem declarando qualquer outro bean... Você vai ver que vão existir DUAS instâncias desse bean na sua aplicação!


        [ ]s
        ----
        Victor Hogemann

        On Jul 2, 2009, at 6:15 AM, Bruno Pacheco Lopes da Silva wrote:




        Interessante, dessa eu não sabia, então isso explica o problema que eu tive ao rodar aquela aplicação citada anteriormente no Ubuntu, pois seria praticamente impossível que a JVM falhasse no escalonamento das threads.

        Vlw, brother.

        Ah, já ia me esquecendo, acabou passando e eu nem comentei, uma dúvida, Spring não é um framework, e Singleton não é um padrão de projeto? Qual seria a relação aqui? Até onde eu sei, no caso do singleton, para que este seja bem aplicado é o desenvolvedor quem deve torná-lo thread safe. Geralmente se utiliza para singleton o conceito de monitor para tratar a concorrência.
         
        Bruno Pacheco - Rio de Janeiro - BR



        From: Victor Hogemann <victor.hogemann@ gmail.com>
        To: riojug@yahoogroups. com
        Sent: Wednesday, July 1, 2009 11:20:53 PM
        Subject: Re: [riojug] Como fazer um Pedido (shopping cart) totalmente thread-safe?

        Bruno,


        Desde a versão 1.3 o Java utiliza system threads no Linux, então o controle das threads fica com o OS mesmo. Tanto que cada thread do Java aparece como um processo separado, já que as threads no Linux são implementadas como processos clonados.

        [ ]s
        ----
        Victor Hogemann

        On Jul 1, 2009, at 9:59 PM, Bruno Pacheco Lopes da Silva wrote:




        Esclarecemos algumas coisas.

        Em um processador com mais de um núcleo, o acesso a fila de processos realmente não é simultâneo, obviamente pois não posso ter o mesmo processo executando em mais de um núcleo. Mas não é aqui que se leva em consideração o paralelismo, mas sim na execução do processo.

        A ideia de ter múltiplos processadores é antiga e, como foi dito anteriormente, o Windows já carrega isso já a algum tempo, mesmo que de forma obscura para alguns. Só para citar um exemplo interessante, no semestre retrasado fiz uma pequena aplicação em java para demonstrar a ideia do uso de semáforos para tratar concorrência. Fiz testes em três SOs diferentes, Um Windows XP Pro, um FreeBSD 7.0 e um Ubuntu 8.04. Os dois primeiros executaram a aplicação conforme o planejado, já no Ubuntu algumas threads simplesmente morriam antes do esperado ou simplesmente não parava de executar. (Isso não ocorreu num Debian posteriormente testado, é claro XD). Enfim, neste caso o SO que apresentou o melhor escalonamento, da forma mais "justa", foi o Windows XP.

        Quanto ao Java, quem controla a execução das threads é a JVM, e não o SO, portanto, uma aplicação java, sem levarmos em consideração outros fatores, como multiplos servidores que atendem a uma determinada fila de requisição por exemplo, não é de fato multiprocessado, salvo aplicações que rodem em Solaris e seus derivados, neste cada thread é uma thread nativa.
         
        Bruno Pacheco - Rio de Janeiro - BR



        From: Vitor Fernandes <thevitu@gmail. com>
        To: riojug@yahoogroups. com
        Sent: Wednesday, July 1, 2009 8:46:57 PM
        Subject: Re: [riojug] Como fazer um Pedido (shopping cart) totalmente thread-safe?


        Victor,
         
        Por padrão Session Beans (Stateless) em Um container EJB sempre são thread safe.
        E o Scope default de um Bean no Spring e Singleton o que o torna  thread safe.
         
        Ate onde eu entendo do processo de escalonamento:
         
        Eu um processador de um único núcleo.
         
        Eu possuo uma unica fila de processos com N prioridades a serem executados. (Existem algoritimos que organizam a mesma)
        A cada clock tick do cpu um desses processos e atendido.
        Um novo processo somente ira ser atendido quando o processador estiver disponível.
         
        Eu um processador de um mais de um núcleo.
         
        Eu possuo uma fila de processos com N prioridades a serem executados. (Existem algoritimos que organizam a mesma)
        A cada clock tick do cpu um desses processos e atendido pelo nucleo que disponível.
        Um novo processo ira ser atendido imediatamente  enquanto existir um nucleo disponível.
         
        É mais rapido, mas ainda atende um por vez (não é simultaneo).
         
        Sistemas operacionais (como o unix que voce citou) realmente multiprocessados podem trabalhar e gerenciar mais de um processador e dedicar processadores para uma aplicação, como uma JVM. (É simultaneo multiplas threads da mesma aplicação sendo atendidas por processadores diferentes)
         
        Agora nunca vi SO da Microsoft rodando com hardware com mais de um processador.
         
        Em hardwares de alta criticidade onde  todos os componetes são dulplicados (processador, memoria, disco, etc...) todos os processos sofrem fork e rodam simultaneamente em processadores  distintos.
         
        2009/7/1 Victor Hogemann <victor.hogemann@ gmail.com>


        Vitor,


        A diferença entre Thread e Fork não é bem isso.

        Usando o fork você  cria uma nova  instância do  seu processo, uma cópia mesmo, com um segmento  de memória separado  e tudo mais. .. Se você precisa  coordenar  o que as instâ ncias do seu  aplicativo  estão fazendo,  tem que utilizar  alguma técnica  de IPC, já que  como eles nã o compartilham  o mesmo segmento  de memória nã o tem como utilizar  variáveis ou  objetos compartil hados pra fazer  esse controle.  Java não usa  Fork.

        Já utilizando Threads você cria um novo caminho de execução, dentro do mesmo processo. Ou seja, várias threads compartilham o mesmo segmento de memória, então elas podem ter acesso a variáveis e objetos compartilhados, sem precisar recorrer a IPC. Java usa Threads.

        Ao contrário do que você deve pensar, threads da mesma aplicação podem ser distribuidas a processadores diferentes em um sistema multi-processado. Tudo depende da implementação. Um jeito fácil de ver isso acontecendo é olhar qualquer container web rodando no Linux, as threads no Linux são implementadas por debaixo dos panos como processos clonados, então cada thread do Java aparece como um processo independente se você listar com o comando ps.

        http://java. sun.com/develope r/technicalArtic les/Programming/ linux/

        Essas são as diferenças básicas entre fork e threads. Se alguém te falou alguma coisa muito diferente disso, na boa, não sabia do que estava falando.

        Quanto a Monoprocessamento e Multiprocessamento. ..

        O Windows suporta vários processadores desde o NT 3.1, as versões que não suportavam vários processadores morreram com o Windows ME. Se foi a mesma pessoa que te explicou sobre fork e thread, já temos uma explicação para esse seu engano.

        [ ]s
        On Jul 1, 2009, at 12:24 PM, Vitor Fernandes wrote:



        Existe uma diferença em WebServer e Container. 
        Sobre o escalonada (spread):

        http://publib. boulder.ibm. com/infocenter/ wasinfo/v5r1/ /index.jsp? topic=/com. ibm.websphere. zseries.doc/ info/zseries/ ae/crun_wlm_ sessionplacement .html

        Paralelo (thread) e uma coisa, Simultaneo (fork) e outra. Isso fica bem claro quando voce programa em C.

        http://www.codeguru .com/forum/ showthread. php?t=413573

        Depende sim. Voce esta confundindo monoprocessamento com multiprocessamento: 

        http://www.google. com.br/search? hl=pt-BR&q=monoprocessamento +e+multiprocessa mento&btnG=Pesquisa+ Google&meta=&aq=7&oq=monopro

        Um S.O. monoprocessado como o windows por exemplo mesmo com um processador de multiplos núcleos vai continuar trabalhando como se tivesse somente um.

        Citei isso, porque vi tudo isso na graduação. Não estou inventando.

        Se colocar synchronized em tudo a performance do servidor já era.

        2009/6/30 Carlos Moscoso <moscoso.dev@ gmail.com>



        Com certeza pode haver concorrência no servidor. Na dúvida coloca synchronized em tudo!

        2009/6/30 Felipe Cypriano <fmcypriano@gmail. com>


        Não entendi, o que é requisição escalonada?

        Pelo que já li até hoje um sistema web, vou falar do básico sem frameworks. O servlet tem sim requisição (chamadas a métodos) simultânea. Para cada servlet o container mantém uma única instância dele e para cada HTTP request que recebe ele cria uma nova thread que acessa essa única instancia do servlet. Mesmo que tudo esteja no mesmo servidor e mesma JVM cada HTTP request é processado em paralelo, por isso o servlet deve ser thread-safe. Um exemplo de como eu acho que pode exisitr requisições simultâneas em único servidor.

        ---
        Felipe Cypriano


        2009/6/30 Vitor Fernandes <thevitu@gmail. com>



          Desculpe-me, mas requisições simultâneas somente podem existir em um sistema distribuido.
        Requisições a um único servidor são escalonadas.



        2009/6/30 Felipe Cypriano <fmcypriano@gmail. com>


        A sessão é compartilhada por usuário, ela pode responder a mais de uma requisição ao mesmo tempo normalmente. Por usuário é diferente de por chamada feita pelo usuário, o usuário pode abrir outra janela do navegador e continuará na mesma sessão enviando requisições simultâneas ao servidor.

        A chance de ocorrer acesso simultâneo em objeto compartilhado por sessão é menor do que em objetos a nível de aplicação (um servlet por exemplo, ou um spring bean singleton) mas ela existe.

        ---
        Felipe Cypriano


        2009/6/30 Carlos Moscoso <moscoso.dev@ gmail.com>



        Se o carrinho está na sessão não há necessidade de sincronizar porque não haverá acesso concorrente.  Se estiver tudo certo apenas o procedimento  de efetivar  a compra na sua aplicação precisa  ser controlado  por meio do  synchronized (ou transação de banco).


        2009/6/30 Felipe Cypriano <fmcypriano@gmail. com>



        Mas exatamente por estar na sessão que preciso que ele seja thread-safe, já que várias chamadas podem acesso-lo simultaneamente.

        A melhor solução é evitar a compra no último momento quando for persistir no banco, já que alguém poderia começar a fazer um pedido e parar o estoque ficaria errado pelo tempo que durar a sessão. Como dito pelo Rafael Cotta num email anterior.

        Para manter simples durante o momento de salvar o usuário não poderia modificar nada no pedido, é mais simples e fácil de dar manutenção do que implementar esse nível de sincronismo da lista.

        ---
        Felipe Cypriano


        2009/6/30 Felipe Gaúcho <fgaucho@gmail. com>


        O mais comum é colocar o carrinho na sessão do usuário :) e esquecer a
        concorrencia - visto que o carrinho é pequeno, contendo apenas a
        referência a meia dúzia de produtos..

        se o problema for evitar a compra de produtos que não estão no
        estoque, inclua no banco de dados uma flag para marcar produtos "na
        mão do cliente",... . pode ter um temporizador para evitar que o
        produto fique bloqueado muito tempo ou outro truque...

        2009/6/29 Carlos Moscoso <moscoso.dev@ gmail.com>:


        >
        >
        > Não vejo necessidade em sincronizar o acesso à lista de itens se você
        > concorda que eventual incosistência durante a navegação e processo de compra
        > é normal. Dito isso, o problema se resume a evitar que a compra de um item
        > que não existe seja efetivada. Considerando que na sua aplicação existe um
        > comando no caso de uso para confirmar a compra bastaria sincronizar este
        > metodo no seu código, que faz as ultimas validações.
        >
        > ps: Usar transações de banco para modelar esse problema pode comprometer o
        > design da sua aplicação uma vez que cada transação terá o escopo de uma
        > requisição apenas. Pra mim que considera uso de banco de dados relacional um
        > detalhe de implementação não me sentiria confortável nessa situação.
        >
        > 2009/6/29 Felipe Cypriano <fmcypriano@gmail. com>
        >>
        >>
        >> Olá Victor e Rafael,
        >>
        >> É extremamente importante que o estoque seja correto, e que nunca entre um
        >> pedido que deixe o estoque negativo. Basicamente esse é o requisito
        >> principal.
        >>
        >> Eu faço a validação tanto na view quanto na camada de serviço, enquanto o
        >> usuário esta adicionando itens ele ve o que está realmente disponível (não
        >> há "pré-baixa", só quando commita a transação que o estoque é alterado), na
        >> camada de serviço é verificado novamente se nenhum regra foi violada e se
        >> todos os itens estão em estoque, após isso tudo é salvo e commitado.
        >>
        >> Como o objeto de PedidoVenda é compartilhado por sessão eu o fiz como
        >> thread-safe, a única parte que não está 100% thread-safe (se eu não me
        >> engano) é a iteração sobre os itens.
        >>
        >> Eu pensei em proteger a referência em sessão quando o processo de "salvar"
        >> o pedido estivesse em andamento, isso traria thread-safe por confinamento,
        >> pois só o método de salvar tem acesso ao pedido e não mais o usuário atráves
        >> da sessão web. É o que vocês sugeriram ne?
        >>
        >> Outro jeito mais complexo seria ter um método dentro de PedidoVenda que
        >> execute uma chamada generica dentro do lock, por exemplo:
        >>
        >> public interface PedidoVendaIterator {
        >>     public PedidoVendaItem eachItem(PevidoVend aItem item);
        >> }
        >>
        >> public class PedidoVenda {
        >>     public void iterateItems( PedidoVendaItera tor iterator) {
        >>         synchronized (internalLock) {
        >>             for (PedidoVendaItem item : getItens()) {
        >>                     iterator.eachItem( item)
        >>             }
        >>         }
        >>     }
        >> }
        >>
        >> Ou seja, o pedido guardaria o lock e passaria o processamento a um
        >> command. Vocês veem algum problema com isso, além da complexidade?
        >>
        >> Alex, o livro é muito bom mas você vai ficar meio doido - igual a eu -
        >> pensando em concorrência, mas é bom que hoje em dia com cada vez mais
        >> núcleos nos processadores mais precisaremos saber sobre esse assunto.
        >>
        >> Abraços,
        >> ---
        >> Felipe Cypriano
        >>
        >>
        >> 2009/6/29 Rafael Cotta <rcotta@gmail. com>
        >>>
        >>>
        >>> Opa, Cypriano. A minha pergunta é: será que você realmente precisa de
        >>> mecanismos tão sofisticados para gerenciar esse carrinho de compras?
        >>>
        >>> Não sei quais são teus requisitos, mas imagino que os casos em que um
        >>> usuário coloque um ítem em um carrinho e na hora do checkout o ítem
        >>> não existe mais são mínimos. E mesmo assim, eu ficaria muito mais à
        >>> vontade de checar essa condição na hora de fechar a transação, ou
        >>> seja, registrar no banco o pedido, verificar o estoque e dar baixa no
        >>> estoque, no meu entendimento, deveria ficar em uma mesma transação de
        >>> banco.
        >>>
        >>> Caso alguma condição falhe, você pode fazer o tratamento adequado
        >>> (mostrar mensagem ao usuário) e dar rollback que tudo volta ao que era
        >>> antes.
        >>>
        >>> []s
        >>>
        >>> Rafael Cotta
        >>>
        >>> 2009/6/29 Alex Rios <alex.rios1337@ gmail.com>
        >>>
        >>> >
        >>> >
        >>> > Comprei esse livro a pouco tempo, apesar de ainda não poder ajudar vou
        >>> > acompanhar o tópico de perto, pois assunto também muito me interessa...
        >>> >
        >>> > 2009/6/29 Felipe Cypriano <fmcypriano@gmail. com>
        >>> >>
        >>> >>
        >>> >> Olá pessoal,
        >>> >>
        >>> >> Estou refazendo o site aqui da empresa, e desde a primeira versão (a
        >>> >> atual e minha primeira app web) eu já aprendi muita coisa, por isso estou
        >>> >> atualizando (refazendo praticamente) ele todo.
        >>> >>
        >>> >> A base que tenho sobre thread é o livro "Java Concurrency in Practice"
        >>> >> antes dele eu nem sabia prestar atenção nos problemas que acesso concorrente
        >>> >> poderia causar, e concorrencia em web é muito importante.
        >>> >>
        >>> >> O que estou em dúvida é como garantir thread-safe durante a iteração
        >>> >> sobre a lista de itens do pedido, eu estou usando um objeto privado como
        >>> >> lock de toda a classe pois o livro ensina que é melhor fazer para não expor
        >>> >> a "lógica" de thread-safe de sua classe, ou seja, não quebrar o
        >>> >> encapsulamento. Simplificando a classe é assim:
        >>> >>
        >>> >> public class PedidoVenda implements Serializable{
        >>> >>     private int id;
        >>> >>     private Integer numero;
        >>> >>     private Date dataEmissao;
        >>> >>
        >>> >>     private final Object internalLock = new Object(); // Esse é o lock
        >>> >>
        >>> >>     private final List<PedidoVendaItem> itens = new
        >>> >> ArrayList<PedidoVendaItem>();
        >>> >>
        >>> >>     // todos os getters and setters são sincronizados com internalLock
        >>> >>
        >>> >>     public List<PedidoVendaItem> getItens() {
        >>> >>         synchronized (internalLock) {
        >>> >>             return Collections. unmodifiableList (itens);
        >>> >>         }
        >>> >>     }
        >>> >>
        >>> >>     public PedidoVendaItem addItem(final PedidoVendaItem item) {
        >>> >>         if (item == null) {
        >>> >>             throw new IllegalArgumentExce ption("Item não pode ser
        >>> >> nulo.");
        >>> >>         }
        >>> >>
        >>> >>         item.setPedido( this); // PedidoVendaItem é thread-safe
        >>> >>         item.setNumero( proximoNumeroIte m());
        >>> >>         synchronized (internalLock) {
        >>> >>             itens.add(item) ;
        >>> >>         }
        >>> >>         return item;
        >>> >>     }
        >>> >> }
        >>> >>
        >>> >> O pedido fica na sessão web enquanto o usuário esta editando, ao
        >>> >> clicar em salvar a referencia desse pedido é passada à camada de serviço que
        >>> >> faz as validações e salva. Uma das partes da validação é verificar se todos
        >>> >> os itens do pedido estão em estoque, isso implica em percorrer a lista
        >>> >> retornada por getItens(), mas percorrer essa lista não garante que uma
        >>> >> chamada à addItem(item) ou removeItem(item) não será feita.
        >>> >>
        >>> >> A questão é como garantir que o objeto não será modificado durante a
        >>> >> validação?
        >>> >>
        >>> >> Se a explicação ficou confusa só me falar que explico melhor, ou pelo
        >>> >> menos tento.
        >>> >>
        >>> >> Abraços,
        >>> >> ---
        >>> >> Felipe Cypriano
        >>> >
        >>> >
        >>> >
        >>> > --
        >>> > Atenciosamente,
        >>> > Alex Rios - Programmer/Develope r
        >>> > GBS - GeoMidi Business Solutions
        >>> >
        >>> >
        >>
        >
        >
        >
        > --
        > Carlos Alexandre Moscoso
        > 

        -- 
        Looking for a client application for this service:
        http://fgaucho. dyndns.org: 8080/footprint- service/wadl





        -- 
        Carlos Alexandre Moscoso







        -- 
        Carlos Alexandre Moscoso

















      Your message has been successfully submitted and would be delivered to recipients shortly.