c中关于自增操作我测试了一小段代码:
int i = 0;
int increment(){
int j = 0;
return ++j;
}
void main(){
++i;
}
~
~
i是全局变量,j是局部变量,反汇编出来的代码如下:
increment:
pushl %ebp
movl $1, %eax
movl %esp, %ebp
popl %ebp
ret
.size increment, .-increment
.p2align 4,,15
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
addl $1, i
popl %ebp
ret
可以看到关于自增运算的指令都是一条指令,加上一点限制:操作数是32位并且没有跨页,这是在C中;
下面看看java中:
public class increment{
public static int i = 0;
public static void main(String ar[]){
increment ic = new increment();
int j = 0;
ic.i++;
j++;
System.out.println(i+" "+j);
}
}
我这里同样设置了类变量和局部变量,下面是javap的部分结果:
7: astore_1
8: iconst_0
9: istore_2
10: aload_1
11: pop
12: getstatic #4; //Field i:I //开始的是对i的运算
15: iconst_1
16: iadd
17: putstatic #4; //Field i:I //i运算结束
20: iinc 2, 1 //j运算
可以看到java中对于局部变量和全局变量关于++操作的不一致,类变量的自增操作不是原子性的,通过getstatic ,iadd,putstatic 得出,是分别进行读,修改,写,而j的运算仅仅是一条iinc指令,局部变量是原子性的。。补充一下,不仅仅是类变量,实例变量(就算是没有声明static),它的自增操作也不是原子性的。
至于为什么java这么设计我想很简单吧,类的静态变量是所有实例进行共享,不是放在某一个方法栈中的,这个变量是这个类型的属性,对这个类变量的更改自然导致了所有实例的“状态”更改,而局部变量在方法返回之后是失去其作用域的。
友情链接:http://madbean.com/2003/mb2003-44/
分享到:
相关推荐
例如,通过AtomicInteger类演示了如何安全地实现自增操作。 除了基本类型,文档还涉及到了数组类型原子更新类,例如AtomicIntegerArray、AtomicLongArray和AtomicReferenceArray。这些类支持对数组元素的原子更新,...
每次获取新ID时,只需要调用`incrementAndGet()`方法,该方法会原子性地增加当前值并返回新的值。 2. **数据库序列**:如果使用的是支持序列的数据库(如Oracle),可以通过建立序列对象并在Java代码中查询来获取新...
这些变量在多线程环境中可以保证其基本操作(如读取、写入或更新)的原子性,即这些操作不会被其他线程打断。例如: ```cpp std::atomic<int> atomic_value; ``` 2. **原子操作(Atomic Operations)** `std::...
`AtomicInteger`是Java提供的原子整型类,它内部通过循环CAS(Compare and Swap)操作来实现线程安全的自增操作,而不需要显式地加锁解锁。 **示例代码**: ```java AtomicInteger count = new AtomicInteger(); count...
以`AtomicInteger`的`getAndIncrement()`为例,这个方法在不发生数据竞争的情况下,可以确保自增操作的线程安全。其内部主要依赖于`Unsafe`类的`compareAndSwapInt()`方法,这是一个原生方法,使用了CAS(Compare ...
原子类的核心特性在于它们的更新操作是原子性的,也就是说,这些操作不会被其他线程中断,一次只有一个线程可以执行。这在多线程环境下是非常重要的,因为它避免了竞态条件,确保了数据的一致性。 1. 原子变量类: ...
在Java中,对基本数据类型的变量进行读取和赋值操作是原子性的,但是像复合操作(例如自增)就不是原子的。解决原子性问题的方案包括使用synchronized关键字、Lock接口实现类以及CAS(Compare-And-Swap)操作。 ...
运行这段代码,你会发现`volatileCounter`的值可能会小于`atomicCounter`,因为`volatile`无法保证自增操作的原子性。 总结起来,`volatile`关键字在Java中主要用于解决并发时的数据可见性问题,但并不保证操作的...
在Java中,基础类型的读写操作通常具有原子性,但对于复合操作如自增(i++)或自减(i--)并不具备原子性。这是因为这些操作实际上涉及多个步骤,如读取、计算和存储,这些步骤在多线程环境下可能会交错执行,导致...
这可以通过调用 `findAndModify` 命令实现,该命令可以在更新文档的同时返回更新后的结果,保证了操作的原子性,避免了并发问题。以下是如何增加 `id` 字段并获取新值的代码: ```bash # 使用findAndModify更新并...
例如,对于volatile变量的自增操作(i++),这个操作包括读取、增加和写回三个步骤,这三个步骤在多线程环境下不是原子的,可能会出现线程安全问题。在上述示例中,`Conter.inc()`方法中的`count++`操作,即使count...
在多线程环境下,简单的计数器自增操作如果不加以同步控制,可能会导致数据不一致。例如,两个线程各自独立地对同一个静态变量count进行累加,最终结果可能不会是200。为了解决这个问题,我们可以使用`synchronized...
原子性则涉及到多线程环境下操作的不可分割性,volatile不能提供完全的原子性,但对于单个读写操作来说,它可以保证原子性。 总的来说,Java内存模型通过规范线程对内存的访问,确保在并发环境下程序的正确性和数据...
`increment()`方法使用`incrementAndGet()`方法来进行自增操作,该方法会原子地增加`AtomicInteger`的值,并返回新的值。`getCount()`方法则返回当前的计数值。 #### 六、为何使用`AtomicInteger` 1. **线程安全性...
这些类提供了无锁的、基于CAS操作(Compare and Swap)的原子性更新,从而避免了锁的使用。CAS操作是一种硬件级别的原语,能够在不使用锁的情况下保证数据的一致性。 原子变量类的特性如下: 1. **无等待和无锁定**...
但volatile不能保证原子性,例如,自增操作在多线程环境下可能会出现问题。 2. **synchronized关键字**:synchronized 提供了更强大的内存可见性和原子性保证。它保证了在同一时刻,只有一个线程可以执行某个同步...
synchronized可以保证整个代码块或方法的原子性,而原子类如AtomicInteger、AtomicLong等能保证特定的原子操作,如自增、自减等。 JVM Memory Model.vsd可能是一个Visio绘制的关于JVM内存模型的图表文件,它可能...
自增操作i++涉及读取、修改和写回三个步骤,也非原子操作。要实现基本类型的原子操作,可以使用synchronized关键字或java.util.concurrent.atomic包下的原子类。 可见性 在并发编程中,可见性指的是一个线程对共享...
8. **事务处理**:确保编号生成和数据插入是原子操作,防止因异常导致的编号重复或丢失。 9. **设计模式**:可以使用工厂模式或策略模式来封装编号生成逻辑,使得代码更易维护和扩展。 综上所述,实现.NET中新增...
例如,对于一个整型变量的自增操作,在没有额外的同步措施的情况下,并不是原子性的,因为它涉及到读取旧值、计算新值和写入新值三个步骤,任何中间步骤被打断都可能导致数据不一致。 2. **可见性问题**:当一个...