Autor
|
Tema: Acceder y modificar una variable global desde distintos threads (Leído 5,249 veces)
|
fileteruso
Desconectado
Mensajes: 18
|
Buenas, estoy intentando que una variable global de tipo int sea modificada por dos tipos de procesos: uno que le suma 1 y otro que le resta 1. Para ello he creado dos clases que implementan Runnable: una llamada Incrementador y otra llamada Decrementador. El problema que tengo es que no se cómo hacer para que desde la clase principal que crea e inicia los procesos se comparta la variable para ir sumándole y restándole uno simultáneamente un número de veces concretas. He intentado pasarla cuando instancio ambas clases en la principal antes de iniciar los procesos pero en el momento que paso por parámetro la variable que se modifica es la propia de las clases Incrementador y Decrementador. (En el código de la clase principal de a continuación solo ejecuto el proceso del incrementador para comprobar si le suma 1) Código clase principal: public class Principal { public static volatile int x = 0; public static void main(String[] args) { Incrementador inc = new Incrementador(x); Thread hilo = new Thread(inc); hilo.start(); System.out.println(x); } }
Código del incrementador: public class Incrementador implements Runnable { private int x; public Incrementador(int x) { this.x = x; } public void run() { x=x+1; } }
Código del Decrementador: public class Decrementador implements Runnable { private int x; public Decrementador(int x) { this.x = x; } public void run() { x=x-1; } }
Muchas gracias de antemano!
|
|
« Última modificación: 6 Febrero 2019, 20:25 pm por fileteruso »
|
En línea
|
|
|
|
ivancea96
Desconectado
Mensajes: 3.412
ASMático
|
La razón de que actualmente no te funcione es que los tipos primitivos como int se copian cuando los pasas como parámetro. Al copiarse, es otro objeto diferente, y aunque lo modifiques, el original se queda igual. Para pasar objetos, tendrías que utilizar clases en vez de tipos primitivos.
Tendrías que meter la variable dentro de una clase y compartir un objeto de esa clase con las 2 que lo van a modificar. Otra opción es tenerlo como variable static y que accedan directamente a ella.
Dado que el acceso concurrente te acabaría dando problemas, puedes usar la clase AtomicInteger que sirve precisamente para eso: Modificar un int desde varios hilos. Podrías crearla en el main, y pasárselo al constructor de los otros 2 como haces ahora.
|
|
|
En línea
|
|
|
|
fileteruso
Desconectado
Mensajes: 18
|
Tomo nota, muchísimas gracias.
|
|
|
En línea
|
|
|
|
rub'n
Conectado
Mensajes: 1.218
(e -> λ("live now")); tatuar -> λ("α");
|
fileteruso que tal usa geshi, para que en un entorno de concurrencia un recurso compartido se actualize de manera correcta necesitas un lock con synchronized usandolo tanto en el método(no recomendado) y/O forma de bloque.
@ivancea96 con clases Atómicas no basta para que un recurso compartido sea actualizado correctamente por múltiples hilos a la misma ves, tampoco basta con volatile se necesita un lock, para asegurar la correcta sincronización.
Lo podemos ver con un ejemplo simple con 20 Hilos, linea 18, y usando un ExecutorService que es mejor que usar directamente la clase Thread o Runnable.
package foro import java.util.Objects; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Logger; import java.util.stream.IntStream; public class UsoSynchronized { private static final Logger LOGGER = Logger. getLogger(Principal. class. getSimpleName()); private ExecutorService executors = null; private volatile int count = 0; private AtomicInteger atomicInteger = new AtomicInteger(0); public UsoSynchronized() { try { executors = Executors.newFixedThreadPool(20); IntStream.rangeClosed(1,10) .forEach(e -> { executors.submit(()-> withAtomicInteger()); }); }finally { if(Objects.nonNull(executors)) { executors.shutdown(); // ayuda a evitar memory leaks, fugas de memoria } } } public void hola() { synchronized (this) { LOGGER.info("Hola " + (++count)); } } public void withAtomicInteger() { //synchronized (this) { LOGGER.info(""+ atomicInteger.incrementAndGet()); //} } public static void main (String... haga) { new UsoSynchronized(); } } }
Feb 06, 2019 10:48:29 PM foro withAtomicInteger INFORMACIÓN: 5 Feb 06, 2019 10:48:29 PM foro withAtomicInteger INFORMACIÓN: 10 Feb 06, 2019 10:48:29 PM foro withAtomicInteger INFORMACIÓN: 9 Feb 06, 2019 10:48:29 PM foro withAtomicInteger INFORMACIÓN: 8 Feb 06, 2019 10:48:29 PM foro withAtomicInteger INFORMACIÓN: 7 Feb 06, 2019 10:48:29 PM foro withAtomicInteger INFORMACIÓN: 6 Feb 06, 2019 10:48:29 PM foro withAtomicInteger INFORMACIÓN: 2 Feb 06, 2019 10:48:29 PM foro withAtomicInteger INFORMACIÓN: 3 Feb 06, 2019 10:48:29 PM foro withAtomicInteger INFORMACIÓN: 4 Feb 06, 2019 10:48:29 PM foro withAtomicInteger INFORMACIÓN: 1
Ese resultado de arriba es única y llanamente debido por que no se tiene un lock lo comente apropósito al invocar al método withAtomicInteger() en la linea 21, y cada Hilo entra a modificar el recurso count, e incluso lo ideal siempre es un bloque lock, es decir no usar synchronized en el método debido a que hay mas costo en el performance de ejecución, es mejor localizar justo el recurso que se modificara, tarea no tan fácil de hacer la mayoría de las veces
Otro ejemplo con 3 hilos, lo hize por la brevedad, nasty, usando atomic Integer y con lock comentadopublic class UsoSynchronized2 { private int count= 0; private AtomicInteger atomicInteger = new AtomicInteger(0); public UsoSynchronized2() { } private void init (final String msg ) { // synchronized (this) { System. out. println(msg + atomicInteger. incrementAndGet()); // } } public static void main (String ... blabl) { UsoSynchronized2 usoSynchronized2 = new UsoSynchronized2(); IntStream.rangeClosed(1,100) .forEach( e -> { new Thread(() -> usoSynchronized2. init("Hilo 1 ")). start(); new Thread(() -> usoSynchronized2. init("Hilo 2 ")). start(); new Thread(() -> usoSynchronized2. init("Hilo 3 ")). start(); }); }
Hilo 1 1 Hilo 2 2 Hilo 3 3 Hilo 3 4 Hilo 1 5 Hilo 2 6 Hilo 1 7 Hilo 2 8 Hilo 3 9 Hilo 3 10 Hilo 2 11 Hilo 3 12 Hilo 2 13 Hilo 1 14 Hilo 2 15 Hilo 1 16 Hilo 1 17 Hilo 2 18 Hilo 2 19 Hilo 1 20 Hilo 1 21 Hilo 2 22 Hilo 1 23 Hilo 2 24 Hilo 3 25 Hilo 1 26 Hilo 1 27 Hilo 3 28 Hilo 1 29 Hilo 1 30 Hilo 3 31 Hilo 1 32 Hilo 2 33 Hilo 2 34 Hilo 1 35 Hilo 3 36 Hilo 2 43 Hilo 3 42 Hilo 3 41 Hilo 2 40 Hilo 2 39 Hilo 1 38 Hilo 1 37 Hilo 2 44 Hilo 3 45 Hilo 1 46 Hilo 1 47 Hilo 1 48 Hilo 2 49 Hilo 3 50 Hilo 2 51 Hilo 2 52 Hilo 3 53 Hilo 1 54 Hilo 2 55 Hilo 2 56 Hilo 1 57 Hilo 1 60 Hilo 3 61 Hilo 2 59 Hilo 2 62 Hilo 3 58 Hilo 1 65 Hilo 2 66 Hilo 3 64 Hilo 1 63 Hilo 3 67 Hilo 1 68 Hilo 2 69 Hilo 3 70 Hilo 1 71 Hilo 1 72 Hilo 3 73 Hilo 3 75 Hilo 1 76 Hilo 3 77 Hilo 2 78 Hilo 2 74 Hilo 1 80 Hilo 1 81 Hilo 2 82 Hilo 3 79 Hilo 2 83 Hilo 1 84 Hilo 3 85 Hilo 1 88 Hilo 3 87 Hilo 2 86 Hilo 3 98 Hilo 1 104 Hilo 3 97 Hilo 2 96 Hilo 1 95 Hilo 2 109 Hilo 2 94 Hilo 3 93 Hilo 3 92 Hilo 1 91 Hilo 1 113 Hilo 1 114 Hilo 1 90 Hilo 1 89 Hilo 1 123 Hilo 1 132 Hilo 2 133 Hilo 3 121 Hilo 2 120 Hilo 1 119 Hilo 2 118 Hilo 2 117 Hilo 3 115 Hilo 2 116 Hilo 3 112 Hilo 2 111 Hilo 3 110 Hilo 3 108 Hilo 1 107 Hilo 3 106 Hilo 3 105 Hilo 1 163 Hilo 3 103 Hilo 1 101 Hilo 1 102 Hilo 3 100 Hilo 2 99 Hilo 2 164 Hilo 3 162 Hilo 3 165 Hilo 2 161 Hilo 2 167 Hilo 3 160 Hilo 1 159 Hilo 3 158 Hilo 3 169 Hilo 2 157 Hilo 3 156 Hilo 2 155 Hilo 3 173 Hilo 3 154 Hilo 1 153 Hilo 1 152 Hilo 2 151 Hilo 3 150 Hilo 3 149 Hilo 1 148 Hilo 2 147 Hilo 1 146 Hilo 3 145 Hilo 2 144 Hilo 3 177 Hilo 2 179 Hilo 3 143 Hilo 3 142 Hilo 2 141 Hilo 2 140 Hilo 3 139 Hilo 1 138 Hilo 2 137 Hilo 1 182 Hilo 3 136 Hilo 3 183 Hilo 2 135 Hilo 2 134 Hilo 2 131 Hilo 1 130 Hilo 3 129 Hilo 3 128 Hilo 3 127 Hilo 1 188 Hilo 2 126 Hilo 2 125 Hilo 1 124 Hilo 3 122 Hilo 3 190 Hilo 3 189 Hilo 2 187 Hilo 2 186 Hilo 3 185 Hilo 1 184 Hilo 2 181 Hilo 3 180 Hilo 2 178 Hilo 1 176 Hilo 1 175 Hilo 2 174 Hilo 2 172 Hilo 1 171 Hilo 1 170 Hilo 1 168 Hilo 3 166 Hilo 2 191 Hilo 1 192 Hilo 2 193 Hilo 3 194 Hilo 1 195 Hilo 3 196 Hilo 1 197 Hilo 2 198 Hilo 1 199 Hilo 2 200 Hilo 1 201 Hilo 2 202 Hilo 2 203 Hilo 2 204 Hilo 1 205 Hilo 3 206 Hilo 2 207 Hilo 2 208 Hilo 3 209 Hilo 3 210 Hilo 1 211 Hilo 1 212 Hilo 1 213 Hilo 2 214 Hilo 1 215 Hilo 3 216 Hilo 2 217 Hilo 1 218 Hilo 3 219 Hilo 2 220 Hilo 2 221 Hilo 3 222 Hilo 3 223 Hilo 2 224 Hilo 1 225 Hilo 3 226 Hilo 1 227 Hilo 3 228 Hilo 2 229 Hilo 2 230 Hilo 1 231 Hilo 2 232 Hilo 3 233 Hilo 1 234 Hilo 3 235 Hilo 1 236 Hilo 3 237 Hilo 1 238 Hilo 2 239 Hilo 3 240 Hilo 1 241 Hilo 3 242 Hilo 1 243 Hilo 1 244 Hilo 3 245 Hilo 2 246 Hilo 1 247 Hilo 2 248 Hilo 3 249 Hilo 1 250 Hilo 2 251 Hilo 3 252 Hilo 1 253 Hilo 2 254 Hilo 3 255 Hilo 1 256 Hilo 2 257 Hilo 3 258 Hilo 2 259 Hilo 3 260 Hilo 1 261 Hilo 1 262 Hilo 2 263 Hilo 3 264 Hilo 2 265 Hilo 3 266 Hilo 1 267 Hilo 2 268 Hilo 3 269 Hilo 1 270 Hilo 3 271 Hilo 1 272 Hilo 2 273 Hilo 3 274 Hilo 2 275 Hilo 3 276 Hilo 1 277 Hilo 3 278 Hilo 1 279 Hilo 2 280 Hilo 1 281 Hilo 3 282 Hilo 2 283 Hilo 3 284 Hilo 1 285 Hilo 2 286 Hilo 3 287 Hilo 2 288 Hilo 2 289 Hilo 1 290 Hilo 1 291 Hilo 1 292 Hilo 3 294 Hilo 3 293 Hilo 3 296 Hilo 2 295 Hilo 2 297 Hilo 3 298 Hilo 2 299 Hilo 1 300
caso distinto tendriamos si usamos el lockprivate void init (final String msg ) { synchronized (this) { System. out. println(msg + atomicInteger. incrementAndGet()); } }
Hilo 1 1 Hilo 3 2 Hilo 2 3 Hilo 2 4 Hilo 1 5 Hilo 1 6 Hilo 2 7 Hilo 1 8 Hilo 3 9 Hilo 2 10 Hilo 1 11 Hilo 2 12 Hilo 1 13 Hilo 3 14 Hilo 2 15 Hilo 3 16 Hilo 2 17 Hilo 1 18 Hilo 2 19 Hilo 3 20 Hilo 1 21 Hilo 3 22 Hilo 2 23 Hilo 3 24 Hilo 1 25 Hilo 3 26 Hilo 2 27 Hilo 1 28 Hilo 3 29 Hilo 3 30 Hilo 2 31 Hilo 1 32 Hilo 3 33 Hilo 1 34 Hilo 2 35 Hilo 3 36 Hilo 2 37 Hilo 1 38 Hilo 3 39 Hilo 2 40 Hilo 2 41 Hilo 1 42 Hilo 1 43 Hilo 2 44 Hilo 3 45 Hilo 3 46 Hilo 2 47 Hilo 1 48 Hilo 2 49 Hilo 1 50 Hilo 2 51 Hilo 3 52 Hilo 1 53 Hilo 3 54 Hilo 1 55 Hilo 3 56 Hilo 2 57 Hilo 1 58 Hilo 2 59 Hilo 3 60 Hilo 3 61 Hilo 2 62 Hilo 1 63 Hilo 2 64 Hilo 1 65 Hilo 3 66 Hilo 3 67 Hilo 1 68 Hilo 2 69 Hilo 3 70 Hilo 1 71 Hilo 1 72 Hilo 2 73 Hilo 3 74 Hilo 3 75 Hilo 2 76 Hilo 1 77 Hilo 3 78 Hilo 2 79 Hilo 1 80 Hilo 3 81 Hilo 2 82 Hilo 1 83 Hilo 3 84 Hilo 2 85 Hilo 1 86 Hilo 3 87 Hilo 2 88 Hilo 1 89 Hilo 3 90 Hilo 3 91 Hilo 2 92 Hilo 1 93 Hilo 1 94 Hilo 3 95 Hilo 2 96 Hilo 3 97 Hilo 1 98 Hilo 2 99 Hilo 3 100 Hilo 1 101 Hilo 2 102 Hilo 2 103 Hilo 3 104 Hilo 1 105 Hilo 3 106 Hilo 1 107 Hilo 2 108 Hilo 1 109 Hilo 1 110 Hilo 3 111 Hilo 1 112 Hilo 1 113 Hilo 2 114 Hilo 3 115 Hilo 3 116 Hilo 3 117 Hilo 1 118 Hilo 1 119 Hilo 2 120 Hilo 3 121 Hilo 1 122 Hilo 2 123 Hilo 3 124 Hilo 1 125 Hilo 2 126 Hilo 3 127 Hilo 2 128 Hilo 2 129 Hilo 2 130 Hilo 3 131 Hilo 1 132 Hilo 2 133 Hilo 3 134 Hilo 1 135 Hilo 2 136 Hilo 3 137 Hilo 1 138 Hilo 2 139 Hilo 3 140 Hilo 1 141 Hilo 2 142 Hilo 1 143 Hilo 2 144 Hilo 3 145 Hilo 2 146 Hilo 3 147 Hilo 2 148 Hilo 1 149 Hilo 2 150 Hilo 3 151 Hilo 1 152 Hilo 3 153 Hilo 3 154 Hilo 1 155 Hilo 2 156 Hilo 1 157 Hilo 2 158 Hilo 3 159 Hilo 2 160 Hilo 1 161 Hilo 3 162 Hilo 2 163 Hilo 3 164 Hilo 2 165 Hilo 3 166 Hilo 1 167 Hilo 1 168 Hilo 1 169 Hilo 3 170 Hilo 2 171 Hilo 3 172 Hilo 3 173 Hilo 1 174 Hilo 1 175 Hilo 3 176 Hilo 1 177 Hilo 2 178 Hilo 1 179 Hilo 3 180 Hilo 1 181 Hilo 3 182 Hilo 1 183 Hilo 2 184 Hilo 3 185 Hilo 3 186 Hilo 1 187 Hilo 2 188 Hilo 3 189 Hilo 1 190 Hilo 2 191 Hilo 2 192 Hilo 1 193 Hilo 2 194 Hilo 2 195 Hilo 3 196 Hilo 1 197 Hilo 3 198 Hilo 2 199 Hilo 2 200 Hilo 2 201 Hilo 2 202 Hilo 1 203 Hilo 2 204 Hilo 3 205 Hilo 1 206 Hilo 2 207 Hilo 2 208 Hilo 1 209 Hilo 3 210 Hilo 3 211 Hilo 3 212 Hilo 1 213 Hilo 2 214 Hilo 2 215 Hilo 2 216 Hilo 1 217 Hilo 3 218 Hilo 1 219 Hilo 3 220 Hilo 3 221 Hilo 1 222 Hilo 1 223 Hilo 1 224 Hilo 1 225 Hilo 1 226 Hilo 2 227 Hilo 2 228 Hilo 3 229 Hilo 2 230 Hilo 3 231 Hilo 2 232 Hilo 2 233 Hilo 3 234 Hilo 1 235 Hilo 2 236 Hilo 1 237 Hilo 2 238 Hilo 2 239 Hilo 3 240 Hilo 3 241 Hilo 3 242 Hilo 3 243 Hilo 3 244 Hilo 1 245 Hilo 3 246 Hilo 2 247 Hilo 2 248 Hilo 2 249 Hilo 3 250 Hilo 1 251 Hilo 2 252 Hilo 3 253 Hilo 3 254 Hilo 1 255 Hilo 3 256 Hilo 2 257 Hilo 1 258 Hilo 1 259 Hilo 1 260 Hilo 2 261 Hilo 2 262 Hilo 2 263 Hilo 3 264 Hilo 1 265 Hilo 1 266 Hilo 2 267 Hilo 1 268 Hilo 3 269 Hilo 2 270 Hilo 1 271 Hilo 1 272 Hilo 2 273 Hilo 3 274 Hilo 3 275 Hilo 1 276 Hilo 2 277 Hilo 3 278 Hilo 1 279 Hilo 2 280 Hilo 3 281 Hilo 1 282 Hilo 2 283 Hilo 1 284 Hilo 3 285 Hilo 1 286 Hilo 3 287 Hilo 1 288 Hilo 3 289 Hilo 2 290 Hilo 3 291 Hilo 1 292 Hilo 3 293 Hilo 1 294 Hilo 2 295 Hilo 2 296 Hilo 1 297 Hilo 3 298 Hilo 3 299 Hilo 2 300
la sincronizacion tiene un efecto bastante duro por el abuso del mismo,DEADLOCK, cuando varios hilos necesitan acceso exclusivo al recurso bloqueandolo/manteniendo el bloqueo, siendo también un bug difícil de detectar
|
|
« Última modificación: 7 Febrero 2019, 07:13 am por rub'n »
|
En línea
|
If you don't have time to read, you don't have the time (or the tools) to write, Simple as that. Stephen king
|
|
|
fileteruso
Desconectado
Mensajes: 18
|
Gracias por una respuesta tan elaborada, pero justamente lo que pretendo no es que funcione de manera sincronizada, sino que falle y provocar una condición de carrera. La finalidad es meramente académica.
Muchísimas gracias otra vez.
|
|
|
En línea
|
|
|
|
fileteruso
Desconectado
Mensajes: 18
|
La razón de que actualmente no te funcione es que los tipos primitivos como int se copian cuando los pasas como parámetro. Al copiarse, es otro objeto diferente, y aunque lo modifiques, el original se queda igual. Para pasar objetos, tendrías que utilizar clases en vez de tipos primitivos.
Tendrías que meter la variable dentro de una clase y compartir un objeto de esa clase con las 2 que lo van a modificar. Otra opción es tenerlo como variable static y que accedan directamente a ella.
Dado que el acceso concurrente te acabaría dando problemas, puedes usar la clase AtomicInteger que sirve precisamente para eso: Modificar un int desde varios hilos. Podrías crearla en el main, y pasárselo al constructor de los otros 2 como haces ahora.
Al final lo he resuelto pasando la propia clase como has dicho. No me ha hecho falta usar AtomicInteger. Dejo el código para quien pudiera estar interesado: Clase principal: public class Principal { public volatile static int x; public Principal() { x = 0; } public static void main(String[] args) throws InterruptedException { Incrementador[] inc = new Incrementador[1000]; Decrementador[] dec = new Decrementador[1000]; Thread hiloinc; Thread hilodec; for(int i=0; i<1000; i++) { inc[i] = new Incrementador(); dec[i] = new Decrementador(); hiloinc = new Thread(inc[i]); hilodec = new Thread(dec[i]); hiloinc.start(); hilodec.start(); hiloinc.join(); hilodec.join(); } System.out.println(x); } }
Clase Incrementador: public class Incrementador implements Runnable { public void run() { Principal.x = Principal.x+1; } }
Clase Decrementador: public class Decrementador implements Runnable { public void run() { Principal.x = Principal.x-1; } }
Gracias a todos!
|
|
« Última modificación: 7 Febrero 2019, 00:12 am por fileteruso »
|
En línea
|
|
|
|
ivancea96
Desconectado
Mensajes: 3.412
ASMático
|
@ivancea96 con clases Atómicas no basta para que un recurso compartido sea actualizado correctamente por múltiples hilos a la misma ves, tampoco basta con volatile se necesita un lock, para asegurar la correcta sincronización.
Las clases del paquete atomic son precisamente thread-safe y lock-free. Son una optimización al uso de locks, y su uso es precisamente este. No sé que pretendías ver en tu ejemplo, pero el resultado es el esperado: La variable ha sido incrementada 10 veces, por tanto, es 10, punto. Puedes verificarlo si quieres: import java.util.Objects; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Logger; import java.util.stream.IntStream; public class UsoSynchronized { private static final Logger LOGGER = Logger.getLogger(UsoSynchronized.class.getSimpleName()); private ExecutorService executors = null; private AtomicInteger atomicInteger = new AtomicInteger(0); public UsoSynchronized() { try { executors = Executors.newFixedThreadPool(20); IntStream.rangeClosed(1,10) .forEach(e -> { executors.submit(()-> withAtomicInteger()); }); } finally { if(Objects.nonNull(executors)) { executors.shutdown(); try { executors.awaitTermination(1, TimeUnit.DAYS); } catch (InterruptedException exc) { } } } LOGGER.info("Final: "+ atomicInteger.get()); } public void withAtomicInteger() { LOGGER.info(""+ atomicInteger.incrementAndGet()); } public static void main(String... haga) { new UsoSynchronized(); } }
Verás un 10 en Final, es lo esperado, y verás los números del 1 al 10 antes que él. Si tú te refieres al orden, evidentemente el orden no es una necesidad en este caso, y como tal, no se mantiene.
|
|
|
En línea
|
|
|
|
|
6666
Desconectado
Mensajes: 146
Wikileaks.org
|
static
|
|
|
En línea
|
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
SMF: $context variable global
PHP
|
[KMT]
|
4
|
3,375
|
2 Enero 2008, 22:02 pm
por [KMT]
|
|
|
variable global
Programación Visual Basic
|
xexio
|
8
|
4,792
|
4 Marzo 2010, 22:12 pm
por xexio
|
|
|
Acceder a una variable privada de una clase desde otra clase
Programación C/C++
|
Alvaro093
|
4
|
30,519
|
27 Enero 2012, 09:46 am
por wachi
|
|
|
variable global
Programación C/C++
|
7emiliosk8
|
1
|
1,828
|
12 Febrero 2017, 13:10 pm
por GGZ
|
|
|
No consigo modificar variable global
Programación C/C++
|
Gamerpc
|
4
|
2,436
|
23 Mayo 2018, 19:07 pm
por Gamerpc
|
|