unity two parse net convertir cast asp c# .net atomic

two - ¿Cómo puedo cambiar de forma atómica 2 ints en C#?



string to int 32 c# (8)

¿Por qué no es Interlocked.Exchange adecuado para usted?

Si necesita que se intercambien las ubicaciones de memoria exactas, entonces está usando el lenguaje y la plataforma incorrectos, ya que .NET abstrae la administración de la memoria para que no tenga que pensar en ello.

Si debe hacer algo como esto sin Interlocked.Exchange , puede escribir un código marcado como unsafe y hacer un intercambio tradicional basado en punteros como lo haría en C o C ++, pero tendría que ajustarlo en un contexto de sincronización adecuado para Que es una operación atómica.

Actualizar
No es necesario recurrir al código unsafe para hacer un intercambio de forma atómica. Puede envolver el código en un contexto de sincronización para hacerlo atómico.

lock (myLockObject) { var x = Interlocked.Exchange(a, b); Interlocked.Exchange(b, x); }

Actualización 2
Si la sincronización no es una opción (como se indica en los comentarios), entonces creo que está fuera de suerte. Mientras persigue cierta eficiencia no medida, es posible que desee concentrarse en otro lugar. Si el intercambio de dos valores enteros es un enorme rendimiento, es probable que esté utilizando la plataforma incorrecta.

¿Cuál (si lo hay) es el equivalente en C # de la instrucción x86 asm xchg ?

Con ese comando, que imo es un intercambio genuino (a diferencia de Interlocked.Exchange ), simplemente podría intercambiar automáticamente dos ints, que es lo que realmente estoy tratando de hacer.

Actualizar:

Código de ejemplo basado en mi sugerencia. Las variables con sufijo "_V" están decoradas como volátiles:

// PART 3 - process links // prepare the new Producer address.ProducerNew.WorkMask_V = 0; // copy the current LinkMask address.ProducerNew.LinkMask_V = address.Producer.LinkMask_V; // has another (any) thread indicated it dropped its message link from this thread? if (this.routerEmptyMask[address.ID] != 0) { // allow all other bits to remain on (i.e. turn off now defunct links) address.ProducerNew.LinkMask_V &= ~this.routerEmptyMask[address.ID]; // reset this.routerEmptyMask[address.ID] = 0; } // PART 4 - swap address.ProducerNew = Interlocked.Exchange<IPC.Producer>(ref address.Producer, address.ProducerNew); // PART 5 - lazily include the new links, make a working copy workMask = address.Producer.LinkMask_V |= address.ProducerNew.WorkMask_V;

Tenga en cuenta la actualización perezosa .


Aquí hay una especie de idea extraña. No sé exactamente cómo ha configurado su estructura de datos. Pero si es posible que pueda almacenar sus dos valores int en un long , entonces creo que podría intercambiarlos atómicamente.

Por ejemplo, digamos que ajustó sus dos valores de la siguiente manera:

class SwappablePair { long m_pair; public SwappablePair(int x, int y) { m_pair = ((long)x << 32) | (uint)y; } /// <summary> /// Reads the values of X and Y atomically. /// </summary> public void GetValues(out int x, out int y) { long current = Interlocked.Read(ref m_pair); x = (int)(current >> 32); y = (int)(current & 0xffffffff); } /// <summary> /// Sets the values of X and Y atomically. /// </summary> public void SetValues(int x, int y) { // If you wanted, you could also take the return value here // and set two out int parameters to indicate what the previous // values were. Interlocked.Exchange(ref m_pair, ((long)x << 32) | (uint)y); } }

Entonces parece que podría agregar el siguiente método de Swap para obtener un par intercambiado "atómicamente" (en realidad, no sé si es justo decir que lo siguiente es atómico; es más como que produce el mismo resultado que un atómico swap ).

/// <summary> /// Swaps the values of X and Y atomically. /// </summary> public void Swap() { long orig, swapped; do { orig = Interlocked.Read(ref m_pair); swapped = orig << 32 | (uint)(orig >> 32); } while (Interlocked.CompareExchange(ref m_pair, swapped, orig) != orig); }

Es muy posible que haya implementado esto incorrectamente, por supuesto. Y podría haber una falla en esta idea. Es solo una idea.


Creo que acabo de encontrar la mejor solución. Es:

Método de intercambio () entrelazado (ref. T, T)

Todas las variables "nuevas" se pueden establecer en una clase (Of T) e intercambiarse con las variables actuales. Esto permite que se produzca una instantánea atómica, mientras se intercambia efectivamente cualquier número de variables.


Esta es la implementación probable para Interlocked.Exchange () en el CLR, copiada de la fuente SSCLI20:

Tenga en cuenta que UP en el nombre de la función significa UniProcessor. Esto no es atómico en sistemas SMP / multi-core. Esta implementación solo será utilizada por CLR en sistemas de un solo núcleo.

FASTCALL_FUNC ExchangeUP,8 _ASSERT_ALIGNED_4_X86 ecx mov eax, [ecx] ; attempted comparand retry: cmpxchg [ecx], edx jne retry1 ; predicted NOT taken retn retry1: jmp retry FASTCALL_ENDFUNC ExchangeUP

Es superior al uso de XCHG porque este código funciona sin tener que bloquear el bus. xchg tiene un prefijo de lock implícito, por lo que, a diferencia de xadd o cmpxchg , simplemente no se puede omitir para que los sistemas de un solo núcleo sigan haciendo la operación en una instrucción para hacerla atómica con respecto a las interrupciones (y, por lo tanto, otras hebras en un uniprocesador).

El código de salto de aspecto extraño es una optimización en caso de que los datos de predicción de rama no estén disponibles. No hace falta decir que quizás, tratar de hacer un mejor trabajo que lo que ha sido considerado durante muchos años por muy buenos ingenieros de software con generosas ayudas de los fabricantes de chips es una tarea difícil.


Fuera de Interlocked.Exchange, asumo que el comando XCHG es probablemente una implementación del Intercambio XOR , por lo que podría escribir el suyo.

Sintaxis C: (desde el enlace de wikipedia)

void xorSwap (int *x, int *y) { if (x != y) { *x ^= *y; *y ^= *x; *x ^= *y; } }

Editar esto no es atómico, tendrías que sincronizarlo tú mismo.


Interlocked.Exchange es la mejor manera de intercambiar dos valores int de una manera segura para subprocesos en c #.

Use esta clase, incluso si tiene una computadora multiprocesador y nunca se sabe en qué procesador se ejecutará el subproceso.


Según Interlocked.Exchange , Interlocked.Exchange es atómico.

Si no es adecuado para usted, puede implementar XCHG en una sección insegura utilizando C / C ++.


Interlocked.Exchange es realmente lo único que puedes hacer:

var x = Interlocked.Exchange(a, b); Interlocked.Exchange(b, x);

Tiene razón en que esto no será atómico, pero con una variable local utilizada, tiene la garantía de que los valores son consistentes siempre que se ejecuten ambas líneas. Sus otras opciones son código no seguro (para usar punteros), usar p / invocar a una biblioteca nativa o rediseñar para que ya no sea necesario.