`

自增操作原子性的理解

阅读更多

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/

 

 

分享到:
评论

相关推荐

    并发编程——原子操作CAS.pdf

    例如,通过AtomicInteger类演示了如何安全地实现自增操作。 除了基本类型,文档还涉及到了数组类型原子更新类,例如AtomicIntegerArray、AtomicLongArray和AtomicReferenceArray。这些类支持对数组元素的原子更新,...

    java快速ID自增器

    每次获取新ID时,只需要调用`incrementAndGet()`方法,该方法会原子性地增加当前值并返回新的值。 2. **数据库序列**:如果使用的是支持序列的数据库(如Oracle),可以通过建立序列对象并在Java代码中查询来获取新...

    C++ 11 开发中的 Atomic 原子操作.rar_C++11、原子_atomic c++_c++ atomic使用_c++

    这些变量在多线程环境中可以保证其基本操作(如读取、写入或更新)的原子性,即这些操作不会被其他线程打断。例如: ```cpp std::atomic<int> atomic_value; ``` 2. **原子操作(Atomic Operations)** `std::...

    java多线程自增效率比较及原理解析

    `AtomicInteger`是Java提供的原子整型类,它内部通过循环CAS(Compare and Swap)操作来实现线程安全的自增操作,而不需要显式地加锁解锁。 **示例代码**: ```java AtomicInteger count = new AtomicInteger(); count...

    Java16个原子类介绍-基于JDK8.docx

    以`AtomicInteger`的`getAndIncrement()`为例,这个方法在不发生数据竞争的情况下,可以确保自增操作的线程安全。其内部主要依赖于`Unsafe`类的`compareAndSwapInt()`方法,这是一个原生方法,使用了CAS(Compare ...

    原子类测试

    原子类的核心特性在于它们的更新操作是原子性的,也就是说,这些操作不会被其他线程中断,一次只有一个线程可以执行。这在多线程环境下是非常重要的,因为它避免了竞态条件,确保了数据的一致性。 1. 原子变量类: ...

    01-并发编程之深入理解JMM&并发三大特性(一).pdf

    在Java中,对基本数据类型的变量进行读取和赋值操作是原子性的,但是像复合操作(例如自增)就不是原子的。解决原子性问题的方案包括使用synchronized关键字、Lock接口实现类以及CAS(Compare-And-Swap)操作。 ...

    java代码-volatile原子性

    运行这段代码,你会发现`volatileCounter`的值可能会小于`atomicCounter`,因为`volatile`无法保证自增操作的原子性。 总结起来,`volatile`关键字在Java中主要用于解决并发时的数据可见性问题,但并不保证操作的...

    4_内存模型2

    在Java中,基础类型的读写操作通常具有原子性,但对于复合操作如自增(i++)或自减(i--)并不具备原子性。这是因为这些操作实际上涉及多个步骤,如读取、计算和存储,这些步骤在多线程环境下可能会交错执行,导致...

    Mongodb自增id实现方法

    这可以通过调用 `findAndModify` 命令实现,该命令可以在更新文档的同时返回更新后的结果,保证了操作的原子性,避免了并发问题。以下是如何增加 `id` 字段并获取新值的代码: ```bash # 使用findAndModify更新并...

    Java并发volatile关键字.docx

    例如,对于volatile变量的自增操作(i++),这个操作包括读取、增加和写回三个步骤,这三个步骤在多线程环境下不是原子的,可能会出现线程安全问题。在上述示例中,`Conter.inc()`方法中的`count++`操作,即使count...

    CAS学习手册-JAVA程序员必备

    在多线程环境下,简单的计数器自增操作如果不加以同步控制,可能会导致数据不一致。例如,两个线程各自独立地对同一个静态变量count进行累加,最终结果可能不会是200。为了解决这个问题,我们可以使用`synchronized...

    【多线程与高并发原理篇:3_java内存模型】.doc

    原子性则涉及到多线程环境下操作的不可分割性,volatile不能提供完全的原子性,但对于单个读写操作来说,它可以保证原子性。 总的来说,Java内存模型通过规范线程对内存的访问,确保在并发环境下程序的正确性和数据...

    使用Java的Memory Model实现一个简单的计数器.txt

    `increment()`方法使用`incrementAndGet()`方法来进行自增操作,该方法会原子地增加`AtomicInteger`的值,并返回新的值。`getCount()`方法则返回当前的计数值。 #### 六、为何使用`AtomicInteger` 1. **线程安全性...

    Java并发编程实践-电子书-08章实用.pdf

    这些类提供了无锁的、基于CAS操作(Compare and Swap)的原子性更新,从而避免了锁的使用。CAS操作是一种硬件级别的原语,能够在不使用锁的情况下保证数据的一致性。 原子变量类的特性如下: 1. **无等待和无锁定**...

    Java并发编程(17)深入Java内存模型-内存操作规则

    但volatile不能保证原子性,例如,自增操作在多线程环境下可能会出现问题。 2. **synchronized关键字**:synchronized 提供了更强大的内存可见性和原子性保证。它保证了在同一时刻,只有一个线程可以执行某个同步...

    Java 内存模型

    synchronized可以保证整个代码块或方法的原子性,而原子类如AtomicInteger、AtomicLong等能保证特定的原子操作,如自增、自减等。 JVM Memory Model.vsd可能是一个Visio绘制的关于JVM内存模型的图表文件,它可能...

    java并发编程常识

    自增操作i++涉及读取、修改和写回三个步骤,也非原子操作。要实现基本类型的原子操作,可以使用synchronized关键字或java.util.concurrent.atomic包下的原子类。 可见性 在并发编程中,可见性指的是一个线程对共享...

    .net实现新增数据时编号自动加一

    8. **事务处理**:确保编号生成和数据插入是原子操作,防止因异常导致的编号重复或丢失。 9. **设计模式**:可以使用工厂模式或策略模式来封装编号生成逻辑,使得代码更易维护和扩展。 综上所述,实现.NET中新增...

    Java并发编程:volatile关键字解析

    例如,对于一个整型变量的自增操作,在没有额外的同步措施的情况下,并不是原子性的,因为它涉及到读取旧值、计算新值和写入新值三个步骤,任何中间步骤被打断都可能导致数据不一致。 2. **可见性问题**:当一个...

Global site tag (gtag.js) - Google Analytics