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

142
Visualizações
Frescura variable de C#

Supongamos que tengo una variable miembro en una clase (con tipo de datos de lectura/escritura atómica):

 bool m_Done = false;

Y luego creo una tarea para establecerlo en verdadero:

 Task.Run(() => m_Done = true);

No me importa cuándo exactamente m_Done se establecerá en verdadero. Mi pregunta es: ¿tengo una garantía por parte de la especificación del lenguaje C# y la biblioteca paralela de Tareas de que eventualmente m_Done será verdadero si accedo a él desde un subproceso diferente?
Ejemplo:

 if(m_Done) { // Do something }

Sé que el uso de bloqueos introducirá las barreras de memoria necesarias y m_Done será visible como verdadero más adelante. También puedo usar Volatile.Write al configurar la variable y Volatile.Read al leerla. Veo mucho código escrito de esta manera (sin bloqueos o volátil) y no estoy seguro de si es correcto.

Tenga en cuenta que mi pregunta no está dirigida a una implementación específica de C# o .Net, sino a la especificación. Necesito saber si el código actual se comportará de manera similar si se ejecuta en x86, x64, Itanium o ARM.

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

0

No me importa cuándo exactamente m_Done se establecerá en verdadero. Mi pregunta es: ¿tengo una garantía por parte de la especificación del lenguaje C# y la biblioteca paralela de Tareas de que eventualmente m_Done será verdadero si accedo a él desde un subproceso diferente?

No.

La lectura de m_Done no es volátil y, por lo tanto, puede retroceder arbitrariamente en el tiempo y el resultado puede almacenarse en caché. Como resultado, se puede observar que es false en cada lectura durante todo el tiempo.

Necesito saber si el código actual se comportará de manera similar si se ejecuta en x86, x64, Itanium o ARM.

La especificación no garantiza que se observará que el código hace lo mismo en modelos de memoria fuertes (x86) y débiles (ARM).

La especificación es bastante clara sobre las garantías que se ofrecen sobre las lecturas y escrituras no volátiles: que pueden reordenarse arbitrariamente en diferentes subprocesos en ausencia de ciertos eventos especiales, como bloqueos.

Lea las especificaciones para conocer los detalles, particularmente la parte sobre los efectos secundarios relacionados con el acceso volátil. Si tiene más preguntas después de eso, publique una nueva pregunta. Esto es algo muy complicado.

Además, la pregunta presupone que está ignorando los mecanismos existentes que determinan que una tarea se complete y, en cambio, está haciendo los suyos propios. Los mecanismos existentes fueron diseñados por expertos; usalos, usalos a ellos.

Veo mucho código escrito de esta manera (sin bloqueos o volátil) y no estoy seguro de si es correcto.

Es casi seguro que no lo es.

Un buen ejercicio para plantearle a la persona que escribió ese código es este:

 static volatile bool q = false; static volatile bool r = false; static volatile bool s = false; static volatile bool t = false; static object locker = new object(); static bool GetR() { return r; } // No lock! static void SetR() { lock(locker) { r = true; } } static void MethodOne() { q = true; if (!GetR()) s = true; } static void MethodTwo() { SetR(); if (!q) t = true; }

Después de la inicialización de los campos, MethodOne se llama desde un subproceso, MethodTwo se llama desde otro. Tenga en cuenta que todo es volátil y que la escritura en r no solo es volátil, sino que está completamente delimitada. Ambos métodos se completan normalmente. ¿Es posible después que s y t se observen como verdaderos en el primer hilo? ¿Es posible en x86? Parece que no; si el primer hilo gana la carrera entonces t sigue siendo falso, y si el segundo hilo gana entonces s sigue siendo falso; este análisis es incorrecto. ¿Por qué? (Pista: ¿cómo se permite que x86 reescriba MethodOne ?)

Si el codificador no puede responder a esta pregunta, es casi seguro que no podrá programar correctamente con volatile y no debería compartir memoria entre subprocesos sin bloqueos.

over 4 years ago · Santiago Trujillo Relatório

0

pruebe este código, cree la versión, ejecútelo sin Visual Studio:

 class Foo { private bool m_Done = false; public void A() { Task.Run(() => { m_Done = true; }); } public void B() { for (; ; ) { if (m_Done) break; } Console.WriteLine("finished..."); } } class Program { static void Main(string[] args) { var o = new Foo(); oA(); oB(); Console.ReadKey(); } }

tienes buenas posibilidades de verlo funcionando para siempre

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