En C es "i+= 1;" ¿atómico?
atomic atomicity (12)
Definido en C, no. En la práctica, tal vez. Escríbelo en conjunto.
El estándar no hace garantías.
Por lo tanto, un programa portátil no haría la suposición. No está claro si quiere decir "requiere ser atómico", o "es atómico en mi código C", y la respuesta a esa segunda pregunta es que depende de muchas cosas:
No todas las máquinas tienen incluso una opción de incremento de memoria. Algunos necesitan cargar y almacenar el valor para operarlo, por lo que la respuesta es "nunca".
En las máquinas que sí tienen una opción de incremento de memoria, no hay garantía de que el compilador no muestre una secuencia de carga, incremento y almacenamiento de todos modos, ni use alguna otra instrucción no atómica.
En las máquinas que sí tienen una operación de incremento de memoria, puede o no ser atómica con respecto a otras unidades de CPU.
En las máquinas que sí tienen una opción de memoria de incremento atómico, no se puede especificar como parte de la arquitectura, sino solo como una propiedad de una edición particular del chip de la CPU, o incluso solo de ciertos diseños de placa madre o lógica central.
En cuanto a "cómo lo hago atómicamente", generalmente hay una manera de hacer esto rápidamente en lugar de recurrir a la exclusión mutua negociada (más cara). A veces esto implica secuencias de códigos repetibles de detección de colisión especiales. Lo mejor es implementarlos en un módulo de lenguaje ensamblador, porque de todos modos es específico de destino, por lo que no hay beneficio de portabilidad para el HLL.
Finalmente, dado que las operaciones atómicas que no requieren una exclusión mutua negociada (costosa) son rápidas y, por lo tanto, útiles y, en cualquier caso, necesarias para el código portátil, los sistemas suelen tener una biblioteca, generalmente escrita en ensamblaje, que ya implementa funciones similares.
En C, es i+=1;
¿atómico?
Aunque no sea atómico para el lenguaje C, cabe señalar que es atómico en la mayoría de las plataformas. La documentación de la Biblioteca GNU C dice:
En la práctica, puede suponer que int y otros tipos de enteros que no sean int son atómicos. También puede suponer que los tipos de puntero son atómicos; eso es muy conveniente Ambas suposiciones son ciertas en todas las máquinas compatibles con la biblioteca C de GNU y en todos los sistemas POSIX que conocemos.
El estándar C no define si es atómico o no.
En la práctica, nunca se escribe un código que falla si una operación dada es atómica, pero también se puede escribir código que falla si no es así . Entonces asume que no es así.
El lenguaje C / C ++ en sí no hace ninguna afirmación de atomicidad o falta de ella. Debe confiar en las funciones intrínsecas o de la biblioteca para garantizar el comportamiento atómico.
La respuesta a su pregunta depende de si i
una variable local, static
o global. Si i
es una variable static
o global, entonces no, la declaración i += 1
no es atómica. Sin embargo, si i
es una variable local, entonces la declaración es atómica para los sistemas operativos modernos que se ejecutan en la arquitectura x86 y probablemente también para otras arquitecturas. @Dan Cristoloveanu estaba en el camino correcto para el caso variable local, pero también hay más que decir.
(En lo que sigue, supongo que un sistema operativo moderno con protección en una arquitectura x86 con subprocesos completamente implementados con conmutación de tareas .)
Dado que este es el código C, la sintaxis i += 1
implica que i
es algún tipo de variable entera, cuyo valor, si es una variable local, se almacena en un registro como %eax
o en la pila. Primero maneje el caso fácil, si el valor de i
está almacenado en un registro, digamos %eax
, entonces el compilador de C muy probablemente traducirá la declaración a algo como:
addl $1, %eax
que por supuesto es atómico porque ningún otro proceso / subproceso debería poder modificar el registro %eax
del subproceso en ejecución, y el subproceso en sí no puede modificar %eax
nuevamente hasta que se complete esta instrucción.
Si el valor de i
se almacena en la pila, esto significa que hay una recuperación de memoria, un incremento y una confirmación. Algo como:
movl -16(%esp), %eax
addl $1, %eax
movl %eax, -16(%esp) # this is the commit. It may actually come later if `i += 1` is part of a series of calculations involving `i`.
Normalmente esta serie de operaciones no es atómica. Sin embargo, en un sistema operativo moderno, los procesos / hilos no deberían poder modificar la pila de otro hilo, por lo que estas operaciones se completan sin que otros procesos puedan interferir. Por lo tanto, el enunciado i += 1
es atómico en este caso.
No Usualmente.
Si i
volatile
, dependerá de tu CPU architecure y tu compilador: si agregar dos enteros en la memoria principal es atómico en tu CPU, entonces esa afirmación C podría ser atómica con una volatile int i
.
No, el estándar C no garantiza la atomicidad y, en la práctica, la operación no será atómica. Debe usar una biblioteca (por ejemplo, la API de Windows ) o las funciones integradas del compilador ( GCC , MSVC ).
No, no lo es. Si el valor de i no está cargado en uno de los registros, no se puede hacer en una sola instrucción de ensamblaje.
No.
La única operación garantizada por el estándar de lenguaje C para ser atómica es asignar o recuperar un valor a / desde una variable de tipo sig_atomic_t
, definida en <signal.h>
.
(C99, capítulo 7.14 Manejo de señal.)
Que la expresión sea atómica o no depende únicamente del código de máquina que genera el compilador y de la arquitectura de la CPU en la que se ejecutará. A menos que la adición se pueda lograr en una instrucción de máquina, es poco probable que sea atómica.
Si está utilizando Windows, puede usar la función API InterlockedIncrement() para hacer un incremento atómico garantizado. Hay funciones similares para decremento, etc.
Realmente depende de su objetivo y del conjunto mnemotécnico de su uC / procesador. Si i es una variable mantenida en un registro, entonces es posible tenerla como atómica.
Solo pon un mutex o un semáforo alrededor. Por supuesto, no es atómico y puedes hacer un programa de prueba con aproximadamente 50 hilos que acceden a la misma variable y aumentarla, para comprobarlo por ti mismo.