Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - xoker

#11
Cita de: ~ Yoya ~ en 19 Enero 2014, 22:53 PM
Fixed

Código (java,13) [Seleccionar]

public class Hilo extends Thread {
private int tipoHilo;
private static Integer n = new Integer(0);
private int nVueltas;

public Hilo(int nVueltas, int tipoHilo) {
this.nVueltas = nVueltas;
this.tipoHilo = tipoHilo;
}

public void run() {

synchronized (n) {

switch (tipoHilo) {
case 0:
for (int i = 0; i < nVueltas; i++)
n = n + 1;

;
break;
case 1:
for (int i = 0; i < nVueltas; i++)
n = n - 1;
;
break;
}
}
}

public static void main(String[] args) throws Exception {
Hilo p = new Hilo(10000, 0);
Hilo q = new Hilo(10000, 1);
p.start();
q.start();
p.join();
q.join();
System.out.println(n);
}

}


La razón porque al principio no funcionaba es porque habías puesto el keyword synchronized dentro del un loop. Cuando se iniciaba un ciclo en el loop, uno de los 2 thread tomaba el lock y el otro esperaba a que liberen el lock.

El problema esta en que el lock se libera cuando termina cada ciclo (son 10,000 ciclos como haz indicado), y puede pasar 2 cosas:

  • El thread que habia tomado el lock toma el lock de nuevo
  • El thread que estaba esperando que liberen el lock toma el lock.

Por lo tanto, en un momento la variable se puede incrementar y en el siguiente puede que disminuya, y en el siguiente puede incrementarse o disminuirse, y asi.

Ahora al poner el keyword al inicio de todo el metodo, el lock se libera solo cuando el metodo se termine de ejecutar, y cuando se termina de ejecutar, entonce el segundo thread puede tomar el lock ya que se ha liberado.

Saludos.



Que? no es como dices, porque tal como tu comentas se ejecutaria todo de manera secuencial, mientras que lo que interesa es el paralelismo lo maximo posible para incrementar el rendimiento.

Poner el synchronized dentro del bucle no tiene problema, ya que la sección critica es el contador (la variable n).

El problema del codigo que puse, es que si utilizas un objeto como cerrojo y lo usas, este se modifica y sus propiedades como cerrojo se pierden y se produce el dichoso entrelazado.

Como dije en el primer comentario, si en vez de poner el cerrojo el objeto n de la clase integer ponemos cualquier otro objeto y este no se modifica en ningun momento, el codigo funcionara perfectamente y no existira entrelazado.

Por cierto, lo de poner el synchronized en el switch es una burrada enorme  :o... porque la gracia de este codigo es ejecutarlo de forma concurrente mientras que tu manera le quita toda la concurrencia posible...
#12
Cita de: xustyx en 18 Enero 2014, 23:13 PM
Código (java) [Seleccionar]

public class Hilo extends Thread {
    private int tipoHilo;
    private  static Integer n = new Integer(0);
    private int nVueltas;


MMM puede ser porque la variable n es privada de la clase hilo????

No se mucho de java pero supongo que esa variable tendría que ser publica y en el main el print seria asi System.out.println(Hilo.n);

Para nada... la encapsulacion de datos es hacerlas privadas aun asi no interfiere en el resultado que sea publica.
#13
Buenas, a ver si me podeis explicar que ocurre con este codigo:

Resulta que deberia de darme un resultado final de cero, pero en vez de eso me da un resultado indeterminado, os pongo aqui el codigo:

public class Hilo extends Thread {
    private int tipoHilo;
    private  static Integer n = new Integer(0);
    private int nVueltas;

    public Hilo(int nVueltas, int tipoHilo)
    {this.nVueltas=nVueltas; this.tipoHilo=tipoHilo;}

    public void run()
    {
     
      switch(tipoHilo){
        case 0:
        for(int i=0; i<nVueltas; i++)
        synchronized(n){ n=n+1;};
        break;
        case 1:
        for(int i=0; i<nVueltas; i++){
        synchronized(n){n=n-1;};
        break;
      }
    }

  public static void main(String[] args)
      throws Exception
  {
      Hilo p = new Hilo(10000, 0);
      Hilo q = new Hilo(10000, 1);
      p.start();
      q.start();
      p.join();
      q.join();
      System.out.println(n);
  }

}


El codigo no esta mal, ya que si cambio el cerrojo de synchronized por otro que no sea de tipo Integer, funciona perfectamente, lo que deja entrever que no se puede usar un cerrojo que se vaya a modificar posteriormente (hago un n++ con la n declarada como integer).

Algun tipo de explicacion de por que no puedo usar este cerrojo? Me he llevado una inmensa sorpresa y dolores de cabeza por culpa de este error!!

Un saludo y gracias!
#14
Java / Duda con pool de threads en java
11 Enero 2014, 20:50 PM
Buenas, tengo una duda con los pool de threads, tengo la siguiente imagen:



Es de un examen que me estoy preparando y resulta, que no tengo ni idea de a que pool de threads puede pertenecer.

Puede ser a un newCachedThreadPool o un ThreadPoolExecutor, creo que tiene mas opciones de ser la segunda, ya que cuando se van creando mas hilos no se resiente el tiempo, cosa que puede corregir el ThreadPoolExecutor...

Que pensais vosotros??
#15
Buenas, termine el programa que trataba de hacer, lo voy a poner aqui por si alguna persona le quiere echar un vistazo o a modo docente por si alguien quiere aprender, tengo mas o menos comentado para que sirve cada linea.

El programa es muy basico y lo que hace es ordenar un vector en orden creciente mediante el algoritmo de la burbuja. Lo ideal seria utilizar funciones en el codigo, pero no se hacerlas aun correctamente, ya que siempre me petan en el ret, se ve que no se guardar bien la direccion a la que debe volver...

;Ordenar un vector dado mediante el algoritmo de la burbuja

.Const

.Data

Vec1 DD 8, 10, 2, 4, 5, 6, 1, 2, 3, 4, 7, 8, 9, 5, 6, 2, 3, 1, 4, 7 ;Aqui esta el vector
Num DD 20 ;Numero de elementos

.Code

start:
Invoke printf, "Vamos a Ordenar el vector Vec1 ya iniciado mediante el algoritmo de la burbuja: "
Invoke puts, "", "\N"               ;Salto de Linea
Invoke printf, "Vector a Ordenar: "
Invoke puts, "", "\N"               ;Salto de Linea

;Imprimir por pantalla el vector:

imprimir:
Mov Ebx, 0 ;Ponemos el contador del bucle a cero.
Mov Esi, Addr Vec1 ;Se le pasa la direccion base para movernos por todo el vector
bucle:
Cmp Ebx, [Num] ;Comparacion de Eax y N
Je > fin ;Salta si Eax y N son iguales, por lo que seria igual a if(Eax < N)
Invoke printf, "%d, ", [Esi] ;Imprime el valor que hay en la direccion de memoria
Inc Ebx ;Eax++
Add Esi, 4 ;Se le suma 4 para movernos sobre el vector elemento a elemento
Jmp < bucle ;Salto incondicional, se usa < porque el salto es hacia atras.
fin:
Invoke puts, "", "\N"               ;Salto de Linea

;Fin parte imprimir Vector por pantalla

;Ordenar los elementos del vector con algoritmo burbuja
burbuja:
Mov Esi, 0 ;Contador i del bucle fuera
Mov Edi, 0 ;Contador j del bucle dentro
Mov Ebx, Addr Vec1 ;Metemos en Ebx la direccion base de vec1 para el bucle de fuera
while_fuera:
Cmp Esi, [Num]
Je > fin_whilefuera ;while(i < Num)
Mov Edi, Esi ;Hacemos j = i al iniciar el bucle
Mov Ebp, Ebx ;Metemos en Ebp la direccion base por donde vamos a empezar que sera en vec1[i]

while_dentro:
Cmp Edi, [Num]
Je > fin_whiledentro ;while(j < Num)
Mov Eax, [Ebx] ;No se pueden comparar [Ebx] y [Ebp] por lo que los hemos pasado a Eax y Ecx
Mov Ecx, [Ebp]
if:
Cmp Eax, Ecx
Jbe > fin_if ;if (Vec1[i] > Vec1[j])
;Invoke printf, "Valor de Vec1[%d]= %d <-- Vec1[%d]= %d, ", Esi, [Ebx], Edi, [Ebp]
;Invoke puts, "", "\N"               ;Salto de Linea
Mov Eax, [Ebx] ;aux1 = vec1[i]
Mov Edx, [Ebp] ;aux2 = vec1[j]
Mov [Ebx], Edx ;vec1[i] = aux2
Mov [Ebp], Eax ;vec1[j] = aux1
fin_if:
Inc Edi ;j++
Add Ebp, 4
Jmp while_dentro ;volvemos al bucle while dentro
fin_whiledentro:
Inc Esi ;i++ al terminar el while_dentro
Add Ebx, 4
Jmp while_fuera ;volveos al bucle while fuera
fin_whilefuera:

;Imprimimos de nuevo los resultados
Invoke printf, "Vector Ordenado: "
Invoke puts, "", "\N"               ;Salto de Linea

imprimir2:
Mov Ebx, 0 ;Ponemos el contador del bucle a cero.
Mov Esi, Addr Vec1 ;Se le pasa la direccion base para movernos por todo el vector
bucle2:
Cmp Ebx, [Num] ;Comparacion de Eax y N
Je > fin2 ;Salta si Eax y N son iguales, por lo que seria igual a if(Eax < N)
Invoke printf, "%d, ", [Esi] ;Imprime el valor que hay en la direccion de memoria
Inc Ebx ;Eax++
Add Esi, 4 ;Se le suma 4 para movernos sobre el vector elemento a elemento
Jmp < bucle2 ;Salto incondicional, se usa < porque el salto es hacia atras.
fin2:
Invoke puts, "", "\N"               ;Salto de Linea


;Fin parte Ordenar los elementos
Exit:
     
Invoke system, "pause"
Xor EAX, EAX
Invoke ExitProcess, EAX

;Fin del programa principal
#16
Cita de: _Enko en  4 Enero 2014, 15:22 PM
Hola, ten cuidado al usar ECX que  la funcion printf por ahi no preserva ecx. Recuerda que los contadores seguros  son esi, edi y ebx.

Te doy una pista si quieres imprimir numeros menores a 10.
8 no es lo mismo que "8"
El primero es un entero. El segundo es un caracter ascii.
El valor del caracter ascii "8" es  56. De "0" 48, "1" es 49...

http://www.asciitable.com/


Luego otro problema.
Vect1 DW....
mov ecx, addr vect1
printf..... [ecx]

printf como parametro te pide un Double Word.
DW creo que significa Data Word.
Necesitas un DD, Data Double Word.
De lo contrario en vez te tomar 8.... te va tomar 98 (primer y segundo elemento del vector invirtiendolos)

Saludos




Gracias por contestar, el tema de los caracteres ASCII no tengo problemas, al menos en C.

Ya he conseguido acceder a la primera posicion, el error era usar el registro Ecx tal como comentaste! He usado Esi y puesto DD en vez de DW (este fue el tipico cambio desesperado...) y a la primera me ha salido el 8. ¿Podrias explicarme un poco mas eso del registro Esi y Ecx? Comprendo que Ecx es un registro que tiene un proposito especifico, pero ¿sabes cual es el problema con printf que se modifica? Elegi el registro Ecx por ya tenia usados Eax y Ebx, vamos por orden, vaya ojo el mio que me fui a fijar en el que se modifica con printf... Ya no se me olvida en la vida!!! :(
#17
Buenas a todos, resulta que como se podran pensar soy muy novato con esto de ensamblador x86 y aqui viene mi duda:

Estoy tratando de imprimir los valores que contiene un vector, les pongo aqui el codigo que tengo por el momento:

.Const

.Data

Vec1 DW 8, 9, 2, 4, 5, 6, 1, 2, 3, 4, 7, 8, 9, 5, 6, 2, 3, 1, 4, 7 ;Aqui esta el vector

.Code

start:

Mov Ecx, Addr Vec1 ;Se le pasa la direccion base para movernos por todo el vector
Mov Eax, 0 ;Contador del vector, se pone el contador a 0

Invoke printf, "El valor de la posicion %d es: %d", Eax,[Ecx] ;[b]Aqui es donde viene la gracia, quiero ver el valor de la posicion 0 del vector y me sale un numero diferente!![/b]
Invoke puts, "", "\N"                                           ;Salto de Linea
Exit:
Invoke system, "pause"
Xor Eax, Eax
Invoke ExitProcess, Eax
;Fin del programa principal


Bueno pues como pongo en el codigo, lo que me ocurre es que en vez de aparecerme la primera posicion del vector lo que me aparece es un numero que no tiene nada que ver y que tampoco es la direccion de memoria del vector.

Creo que la teoria me la conozco y es lo que trato de aplicar, le paso a un registro la direccion donde se encuentra la direccion base del vector, y a partir de ahi voy recorriendo este aumentando la direccion en funcion de lo que ocupen los enteros, en este caso son dw por lo que se incrementara de 2 en 2 bytes, pero en la primera posicion el incremento es cero por lo que con mi codigo tendria que verse... He probado sumandole 2 o mas... quitandole los corchetes a Ecx y mil perradas, pero no lo cosigo  :rolleyes:.

Se que con este codigo no se puede recorrer todo el vector, he puesto aqui solo parte para que se vea la primea posicion para simplificarlo, mi problema solo es ese, con el bucle no tengo problemas (aun... xD)

A ver si me pueden decir donde esta mal el codigo!!

Un saludo!!
#18
Dios, hace años que no veo un GOTO, eso en C esta mas que prohibido, no se si vienes de ensamblador o que estas siguiendo un tutorial de hace mas de 20 años, pero no se cuantos años hace que se desaconsejo el empleo de goto ya que induce a un codigo ilegible y dificilmente modificable, lo que comunmente se llama codigo espaguetti.

Un link de wikipedia donde explica mejor la constroversia con goto: http://es.wikipedia.org/wiki/GOTO

Un saludo!
#19
Cita de: rir3760 en 27 Diciembre 2013, 17:35 PM
Es un tema duplicado, ya le están ayudando en su otro tema: Problemas con los ficheros

En cuanto a fstream es parte de la biblioteca estándar de C++.

Un saludo

Entonces ok, dejo el tema en paz, solo una duda, si la biblioteca fstream es parte del la biblioteca stantart de c++ no se podra agregar en un fichero .c cierto? Y esta claro que esta trabajando con C puesto que las otras bibliotecas conservan el .h

Un saludo.
#20
con scanf no se escribe en un fichero, se escribe con fprintf por ejemplo...

edito: ¿para que sirve fstream? no conozco esa libreria...