Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

392
Visualizações
Al generar, se encuentra que currentId no es 10000 como se esperaba. ¿Por qué? como corregirlo

Este código lo vi por casualidad. El código es más o menos como sigue.

 public class Question2 { public void Run() { List<Task> tasks = new List<Task>(); for (int i = 0; i < 10000; i++) { tasks.Add(Task.Factory.StartNew(() => { GetNextId(); })); } Task.WaitAll(tasks.ToArray()); Console.WriteLine("currentId=" + GetCurrentId()); Console.ReadKey(); } private int currentId; public int GetNextId() { currentId++; return currentId; } public int GetCurrentId() { return currentId; } }

No sé por qué el resultado no es 10000. Alguien me puede decir porque y como corregirlo.

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

¡Acabas de descubrir el tema de la seguridad de subprocesos! currentId++ traduce como

  1. leer el valor de currentId de la memoria
  2. incrementar este valor en uno
  3. escribe este nuevo valor en la memoria

Ahora imagine que su ciclo va solo hasta i < 3. El primer hilo está en el paso 1 y lee el valor 0. Antes de pasar al paso 2, el segundo hilo está en el paso 1 y también lee 0. Ahora ambos hilos van al paso 3, escribirá ambos 1 en la memoria. Ahora comienza el tercer hilo y leerá 1 de la memoria, lo incrementará a 2 y lo escribirá en la memoria. Ahora tiene 2 en lugar del valor esperado 3.

Para solucionar esto, puede usar Interlocked.Increment :

 private int currentId; public int GetNextId() { return Interlocked.Increment(ref currentId); }

Pero tenga en cuenta que, dependiendo de su caso de uso, es posible que aún tenga problemas similares cuando use el valor de retorno de GetNextId() .

over 4 years ago · Santiago Trujillo Relatório

0

currentId++;

En un programa de un solo subproceso, la secuencia de eventos se ve así.

  1. El subproceso lee el valor de currentId (por ejemplo, 999).
  2. El subproceso incrementa el valor y escribe en currentId. El valor de currentId ahora es 1000.

En su programa de subprocesos múltiples, la secuencia de eventos puede parecerse más a esto.

  1. El subproceso 1 lee el valor de currentId (por ejemplo, 999).
  2. El subproceso 2 lee el valor de currentId (también, 999).
  3. El subproceso 3 lee el valor de currentId (también, 999).
  4. El subproceso 2 incrementa el valor y escribe en currentId. El valor de currentId ahora es 1000.
  5. Thread 3 incrementa el valor y escribe en currentId. El valor de currentId ahora es 1000.
  6. El subproceso 1 incrementa el valor y escribe en currentId. El valor de currentId ahora es 1000.

Entonces, el valor de currentId se incrementó tres veces, pero el valor es 1000.

Una solución a este problema es usar la palabra clave lock. El uso de la palabra clave lock garantiza que solo un subproceso tenga acceso a un fragmento de código a la vez.

 private int currentId; private object _object = new object(); public int GetNextId() { lock (_object) { currentId++; return currentId; } }

La secuencia de eventos ahora se ve así.

  1. El subproceso 1 obtiene acceso a la cerradura (_objeto).
  2. El subproceso 1 lee el valor de currentId (por ejemplo, 999).
  3. El subproceso 2 solicita acceso al bloqueo (_objeto) pero se ve obligado a esperar hasta que el subproceso 1 libere el bloqueo.
  4. El subproceso 3 solicita acceso a la cerradura (_objeto). La solicitud se pone en cola detrás de la solicitud del subproceso 2.
  5. El subproceso 1 incrementa el valor y escribe en currentId. El valor de currentId ahora es 1000.
  6. El subproceso 1 libera el bloqueo (_objeto).
  7. El subproceso 2 obtiene acceso a la cerradura (_objeto).
  8. El subproceso 2 lee el valor de currentId (ahora, 1000).
  9. El subproceso 2 incrementa el valor y escribe en currentId. El valor de currentId ahora es 1001.
  10. El subproceso 2 libera el bloqueo (_objeto).
  11. El subproceso 3 obtiene acceso a la cerradura (_objeto).
  12. El subproceso 3 lee el valor de currentId (ahora, 1001).
  13. Thread 3 incrementa el valor y escribe en currentId. El valor de currentId ahora es 1002.
  14. El subproceso 3 libera el bloqueo (_objeto).

Tenga en cuenta que el resultado seguirá siendo 9999 si el valor inicial es cero y lo incrementa 9999 veces.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda