9.9 - Sincronização

O assunto agora é um pouco mais complicado do que o estudado até agora, pois trata de como duas ou mais threads podem compartilhar o mesmo objeto, ou seja, quais são os riscos que corremos quando dois objetos podem ser vistos simultâneamente.

Cenário: 

Imaginemos um processo de compra on-line pela Internet, onde inúmeras pessoam podem consultar os itens disponíveis em estoque e realizar seus pedidos. Pois bem, como não queremos causar situações indigestas com nossos clientes, precisamos garantir com seus pedidos sejam faturados corretamente. Bom onde queremos chegar ? Imagine que temos 5 aparelhos celulares S55 SIEMENS em nosso estoque e que foi lançado uma promoção desse aparelho e 200 pessoas estão dispostas a entrar no tapa por um aparelho, bem temos que garantir que esse processo seja concretizado sem maiores problema. (tudo isso foi dito para se esplanar a situação... ) Vejamos como resolver esse problema:

Não tenter vender o programa acima para alguma loja que você será escurraçado!

O código de efetuar pedido, sempre efetuará o pedido tendo ou não estoque, note que na saída houve 10 cliente que efetuaram seus pedidos com estoque estourado:

Pedido faturado para o cliente Cliente: 0
Pedido faturado para o cliente Cliente: 1
Pedido faturado para o cliente Cliente: 2
Pedido faturado para o cliente Cliente: 3
Pedido faturado para o cliente Cliente: 5
Pedido faturado para o cliente Cliente: 6
Pedido faturado para o cliente Cliente: 8
Pedido faturado para o cliente Cliente: 9
Pedido faturado para o cliente Cliente: 10
Pedido faturado para o cliente Cliente: 11
Pedido faturado para o cliente Cliente: 4
Pedido faturado para o cliente Cliente: 7
Pedido faturado para o cliente Cliente: 12
Pedido faturado para o cliente Cliente: 13
Pedido faturado para o cliente Cliente: 14
Pedido faturado para o cliente Cliente: 0
Pedido faturado para o cliente Cliente: 1
Pedido faturado para o cliente Cliente: 2
Pedido faturado para o cliente Cliente: 3
Nao tem estoque para o cliente Cliente: 5
Nao tem estoque para o cliente Cliente: 6
Nao tem estoque para o cliente Cliente: 8
Nao tem estoque para o cliente Cliente: 9
Nao tem estoque para o cliente Cliente: 11
Nao tem estoque para o cliente Cliente: 10
Nao tem estoque para o cliente Cliente: 4
Nao tem estoque para o cliente Cliente: 12
Nao tem estoque para o cliente Cliente: 7
Nao tem estoque para o cliente Cliente: 13
Nao tem estoque para o cliente Cliente: 14

O que queremos é não permitir que haja faturamento caso o estoque esteja negativo.
Pelo resultado não é muito difícil deduzir o que aconteceu nesse processamento - embora você possa executar e obter outro resultado. Observe que todos os pedidos só foram efetuados porque há no método efetuarPedido uma suspensão da execução das thread para sua concretização, ou seja, até o momento em que a thread volta após sua suspensão, o pedido ainda não foi efetuado, com isso, outros clientes podem efetuar seus pedidos - quando esse ciclo se repetir para os 5 primeiros clientes, aí sim, não será mais possível concretizar pedidos, pois o estoque do item se tornou 0. Porém não foi exatamente isso que aconteceu em nosso exemplo anterior. E você é capaz de descobrir porque ?

A grande sacada do programa anterior é suspender a thread por um tempo para que antes de concluir sua operação, dando lugar as outras, fazendo com que o estoque fique negativo.

Mas existe uma solução para que esse "erro" seja revertido, ou seja, não permitir que dois clientes possam concluir seus pedidos ao mesmo tempo.
