entanglement 31 de jul. de 2012
GilsonNunes 31 de jul. de 2012
obrigado entanglement, vou dar uma olhada.
eu tinha criado uma solução caseira aki, apesar de ter funcionando, não ousei postar aki não.
GilsonNunes 31 de jul. de 2012
mas já q estamos aki é pra aprender mesmo, me desculpem por qq coisa tosca.
public class TesteSync3 {
private int [] valores = new int [ 10 ] ;
private static final int QTDE_THREADS = 10 ;
private LockRW lock = new LockRW ();
public void exec (){
for ( int i = 0 ; i < valores . length ; i ++ ) {
valores [ i ] = 0 ;
}
for ( int i = 0 ; i < QTDE_THREADS ; i ++ ) {
new TesteThread ( i + 1 ). start ();
}
new Thread (){
public void run () {
int vv = 0 ;
while ( true ) {
vv ++ ;
lock . beginWrite ();
//synchronized (valores)
{
System . out . println ( "beginWrite: " + vv );
for ( int i = 0 ; i < valores . length ; i ++ ) {
valores [ i ] = vv ;
}
System . out . println ( "endWrite: " + vv );
}
lock . endWrite ();
TesteSync3 . sleep ( 3000 );
if ( vv > QTDE_THREADS ){
vv = 0 ;
}
}
};
}. start ();
}
private class TesteThread extends Thread {
private int value ;
public TesteThread ( int value ) {
this . value = value ;
}
private int countEquals (){
int r = 0 ;
for ( int i = 0 ; i < valores . length ; i ++ ) {
if ( valores [ i ] == value )
r ++ ;
TesteSync3 . sleep ( 100 );
}
return r ;
}
@Override
public void run () {
long tTmp = System . currentTimeMillis ();
long tIni = tTmp ;
int qq = 0 ;
while ( true ) {
lock . beginRead ();
//synchronized (valores)
{
int i = countEquals ();
if ( i == valores . length ){
System . out . println ( "***** EQUAL: " + value );
} else if ( i > 0 ){
System . out . println ( "***** Erro: " + value + " " + i );
}
}
lock . endRead ();
qq ++ ;
long t2 = System . currentTimeMillis ();
if ( t2 > tTmp + 10000 ){
System . out . printf ( ">>> ******************Proc: %02d Qtde: %5d Tempo médio: %,5d mm\n" , value , qq , ( t2 - tIni ) / qq );
tTmp = t2 ;
}
}
}
}
public static void main ( String [] args ) {
new TesteSync3 (). exec ();
}
static public void sleep ( int ms ){
try {
Thread . sleep ( ms );
} catch ( InterruptedException e ) {
}
}
}
public class LockRW {
private int lockRead = 0 ;
private int lockedWrite = 0 ;
public void beginRead (){
while ( true ) {
synchronized ( this ) {
if ( lockedWrite == 0 ){
lockRead ++ ;
return ;
}
}
try {
Thread . sleep ( 1 );
} catch ( InterruptedException e ) {
}
}
}
public void endRead (){
synchronized ( this ) {
if ( lockRead > 0 )
lockRead -- ;
}
}
public void beginWrite () {
while ( lockedWrite != 3 ) {
synchronized ( this ) {
lockedWrite = 1 ;
if ( lockRead == 0 ){
lockedWrite = 3 ;
return ;
}
}
}
}
public void endWrite (){
synchronized ( this ) {
lockedWrite = 0 ;
}
}
}
entanglement 1 de ago. de 2012
As vantagens de usar essas classes prontas do JDK , em vez de usar as soluções caseiras , são as seguintes :
a ) Se você usou as classes exatamente do jeito que foram documentadas , elas devem funcionar com certeza ( o que você pode ter dificuldades de afirmar no caso de uma solução caseira - afinal de contas , você não é o dr . Doug Lea , que basicamente desenvolveu toda a parte de concorrência moderna do Java - o pacote java . util . concurrent );
b ) Elas costumam ser muito mais mais rápidas que as soluções caseiras , porque em vez de usar “ synchronized ” , “ wait ” e “ notify ” ( que são operações que usam monitores , que costumam ser muito pesados ) usam alguns locks especiais que foram introduzidos no Java 5 justamente para acelerar os programas que precisam de multiprocessamento ;
c ) Usar um ReadWriteLock e outras classes do java . util . concurrent ( em vez de usar um monte de synchronized , wait e notify ) ajuda a tornar mais claros seus programas , porque você consegue então mostrar que está sendo usado um determinado recurso ( por exemplo , o caso do “ multiple readers , single writer ” ) em vez de isso ficar implícito .
GilsonNunes 1 de ago. de 2012
entanglement, obrigado pelo esclarecimento.
vc está certíssimo.
eu tinha feito esse "caseiro" no intuito de exercitar.
e q tb não conhecia esses q vc postou. agora até ja modifiquei pra funcionar com sua sujestão.
import java.util.concurrent.locks.ReadWriteLock ;
import java.util.concurrent.locks.ReentrantReadWriteLock ;
public class TesteSync4 {
private int [] valores = new int [ 10 ] ;
private static final int QTDE_THREADS = 10 ;
private ReadWriteLock lock = new ReentrantReadWriteLock ();
public void exec (){
for ( int i = 0 ; i < valores . length ; i ++ ) {
valores [ i ] = 0 ;
}
for ( int i = 0 ; i < QTDE_THREADS ; i ++ ) {
new TesteThread ( i + 1 ). start ();
}
new Thread (){
public void run () {
int vv = 0 ;
while ( true ) {
vv ++ ;
lock . writeLock (). lock ();
//synchronized (valores)
{
System . out . println ( "beginWrite: " + vv );
for ( int i = 0 ; i < valores . length ; i ++ ) {
valores [ i ] = vv ;
}
System . out . println ( "endWrite: " + vv );
}
lock . writeLock (). unlock ();
TesteSync4 . sleep ( 3000 );
if ( vv > QTDE_THREADS ){
vv = 0 ;
}
}
};
}. start ();
}
private class TesteThread extends Thread {
private int value ;
public TesteThread ( int value ) {
this . value = value ;
}
private int countEquals (){
int r = 0 ;
for ( int i = 0 ; i < valores . length ; i ++ ) {
if ( valores [ i ] == value )
r ++ ;
TesteSync4 . sleep ( 100 );
}
return r ;
}
@Override
public void run () {
long tTmp = System . currentTimeMillis ();
long tIni = tTmp ;
int qq = 0 ;
while ( true ) {
lock . readLock (). lock ();
System . out . println ( "beginRead: " + value );
//synchronized (valores)
{
int i = countEquals ();
if ( i == valores . length ){
System . out . println ( "***** EQUAL: " + value );
} else if ( i > 0 ){
System . out . println ( "***** Erro: " + value + " " + i );
}
}
System . out . println ( "endRead: " + value );
lock . readLock (). unlock ();
qq ++ ;
long t2 = System . currentTimeMillis ();
if ( t2 > tTmp + 10000 ){
System . out . printf ( ">>> ******************Proc: %02d Qtde: %5d Tempo médio: %,5d mm\n" , value , qq , ( t2 - tIni ) / qq );
tTmp = t2 ;
}
}
}
}
public static void main ( String [] args ) {
new TesteSync4 (). exec ();
}
static public void sleep ( int ms ){
try {
Thread . sleep ( ms );
} catch ( InterruptedException e ) {
}
}
}
entanglement 2 de ago. de 2012
Eu considero “synchronized”, “wait” e “notify”, assim como disparar threads diretamente, em programação concorrente, os equivalentes do “goto” na programação estruturada.
O “goto” é uma primitiva de nível muito baixo que não deve ser usada (tanto é que no Java nem existe o “goto”).
Da mesma maneira, “synchronized”, “wait” e “notify”, assim como as threads, tendem a ser usados de forma incorreta e caótica, tornando os programas pouco compreensíveis e depuráveis.
Dentro da medida do possível, é melhor usar as classes de nível mais alto presentes no pacote java.util.concurrent.
GilsonNunes 3 de ago. de 2012
mas não estou usando nenhum desses.