Problema com Threads [resolvidoo XD q legal]

Olá gente, eu de novo … rsrs e o testKiller …

sei que parece sacanagem rsrs… mas a pergunta abaixo … eu li , li , li coloquei no eclipse, debuguei … li de novo debuguei … e eu não consigo achar porque raios que dá essa resposta … >< eis o código:


public class Transfers { 
	 public static void main(String[] args) throws Exception { 
		 
	
		 Record r1 = new Record(); 
		 Record r2 = new Record(); 
		 doTransfer(r1, r2, 5); 
		 doTransfer(r2, r1, 2); 
		 doTransfer(r1, r2, 1);
	
	 // print the result 
		 System.out.println("rl = " + r1.get() +", r2=" + r2.get()); 
		 	}
		  
	 	private static void doTransfer(final Record a, final Record b, final int amount) { 
	 		Thread t = new Thread() { 
	 			public void run() { 
	 				new Clerk().transfer(a, b, amount); 
	 			} 
	 		}; 
	 		t.start(); 
	 	} 
	 } 
	 
 	class Clerk { 
 		public synchronized void transfer(Record a, Record b, int amount){ 
 			synchronized (a) { 
 				synchronized (b) { 
 					a.add(-amount); 
 					b.add(amount); 
 				} 
 			} 
 		} 
	 } 
	 
 	class Record { 
 		int num=10; 
 		public int get() { 
 			return num; 
		 	} 
 		
 		public void add(int n) { 
 			num = num + n; 
 			}
 		}
	

Opções:

If Transfers.main() is run, which three are true? (Choose three.)
A. The output may be ?r1 = 6, r2 = 14?.
B. The output may be ?r1 = 5, r2 = 15?.
C. The output may be ?r1 = 8, r2 = 12?.
D. The code may run (and complete) with no output.
E. The code may deadlock (without completing) with no output.
F. M IllegalStateException or InterruptedException may be thrown at
runtime.

as corretas são A, B e E

e olhei o código … tudo sincronizado … r1 e r2 são duas instancias distintas… e não entendi o porque dessa possibilidade … de sair esses numeros diferentes …
e
se é possivel acontecer a A e a B porque não é possivel acontecer a C ???

outra coisa que não entendi foi pq a E está correta?
não consigo enchergar aí uma forma do código entrar em empasse… não tem join … não tem wait … não tem spleep …
e outra . … mesmo que entrasse em impasse, de acordo com o livro da kathy a JVM iria escolher uma thread para executar … tornando impossivel travar TUDO e não der nem um outputzinhu rs.

alguém? por favor?

Entao cara, parte do problema esta no fato de que a thread disparada acessa a um metodo sincronizado, porem, voce cria um novo objeto do tipo Clerk toda vez que chama doTransfer, desta maneira nao existe concorrencia entre as Threads por executar o corpo do metodo transfer. Nao sei se fui claro…rsrsr! Resumindo: nova Thread => novo Clerk => disparada essa Thread; nova Thread => novo Clerk => disparada essa Thread e novamente, nova Thread => novo Clerk => disparada essa Thread. Perceba que as tres Threads existentes executam metodos de objetos diferentes, por issa nao temos concorrencia!

Abracao

opa … primeiramente obgado pela resposta

… então cara … por issu mesmo que eu estou confuso … foi o que eu falei no tópico, acho q não fui muito claro

não tem concorrencia mesmo… então PORQUE q dá aqules resultados? a cada execução dá um result diferente … e porque q ele pode dar deadLok?
e porq q se pode dar A e B pq q não pode dar a C?

Esta é das difíceis. Mas vamos lá.

Não há nenhum wait, notify, sleep, join ou qualquer coisa assim que possa lançar IllegalStateException ou InterruptedException. F é falsa.

Se o código completar normalmente (sem deadlock, System.exit, ou exceção), o System.out.println do método main vai ter que executar. Logo D é falsa.

Observe que as três threads entram no método Clerk.transfer tendo como parâmetro os objetos r1 e r2, mas a ordem pode ser diferente.

Vamos chamar as três threads criadas no método doTransfer de T1, T2 e T3, respectivamente.

Ao atingir o método transfer T1 terá a=r1 e b=r2, T2 terá a=r2 e b=r1 e T3 terá a=r1 e b=r2.

Como cada thread tem um Clerk distinto, o fato de estar sincronizado não faz diferença, pois cada Clerk está confinado a uma thread. Porém, o mesmo não ocorre com r1 e r2.

Então, vamos supor que ocorra isso:
T1 chega no synchronized (a), sincronizando em r1.
T2 chega no synchronized (a), sincronizando em r2.
T1 chega no synchronized (b), como T2 é a “dona” de r2, T1 espera T2.
T2 chega no synchronized (b), como T1 é a “dona” de r1, T2 espera T1.
Deadlock!

Alternativa E está quase correta. Estaria se não fosse o “with no output”. Mas isso pode depender de algumas peculiaridades do SO e da JVM.

Observe que o System.out.println está na Thread principal e não espera T1, T2 e nem T3 terminarem. Logo é possível que o System.out.println ocorra antes de as Thread terminarem. Ainda mais que o método get não é sincronizado.

Os dois Record são criados antes de qualquer thread com o valor 10. Então eles garantidamente terão este valor inicial.

Observe que, supondo que a execução das Threads não se sobreponha (ou seja, supondo que uma só comece depois que outra terminar) e que o System.out também não ocorra enquanto alguma Thread está executando, temos as seguintes oito possibilidades.

  1. System.out antes de tudo: r1 = 10, r2 = 10.
  2. T1, System.out: r1 = 5, r2 = 15. (Letra B está correta)
  3. T2, System.out: r1 = 12, r2 = 8. (Isso é o inverso da letra C)
  4. T3, System.out: r1 = 9, r2 = 11.
  5. T1, T2, System.out: r1 = 7, r2 = 13 (a ordem de T1 e T2 não faz diferença)
  6. T1, T3, System.out: r1 = 4, r2 = 16 (a ordem de T1 e T3 não faz diferença)
  7. T2, T3, System.out: r1 = 11, r2 = 9 (a ordem de T2 e T3 não faz diferença)
  8. T1, T2, T3, System.out: r1 = 6, r2 = 14 (a ordem de T1, T2 e T3 não faz diferença) (Letra A está correta)

Há outras possibilidades, de que uma Thread execute enquanto outra está na metade. Porém isso levaria uma Thread a esperar outra por causa dos synchronized, ou causaria o deadlock.
Se o System.out.println ocorrer enquanto alguma Thread está executando, ou ele mostra o resultado antes de a Thread manipular os Records, ou após ela terminar, ou no meio dessa manipulação, gerando um resultado inconsistente (onde r1+r2 != 20).

Logo, não é possível que ocorra C.

EDIT: Pequenas correções.

Caraka veio …

entendi TUDO …

muito obrigado mesmo … tem outra aki q to enrrolado … depois desses toques q vc deu … vo ver se consigo resolver sozinhui
senão eu faço outro post rsrsrs

valewww