在单线程的模式下,我们针对某个变量的修改是不会产生数据的脏读和脏写的,因为它只有一个操作来对变量进行读写操作,但是在多线程模式下就不一样了,如果多个线程对一个变量进行修改操作,那么到底哪一个线程修改的值才是最后的值呢?同时是不是我们需要的值呢?那么我们如何来保证多个线程修改变量值的时候保证变量的原子操作?简单说明下原子操作就是一个步骤要么操作全部成功,要么失败。我们看下i++这个操作,对于不了解这个i++操作生成的二进制文件的具体同学来说,可能会认为它是只有一个操作步骤的运算操作,但是实际情况肯定不是的,它首先会去获取字段i,然后在获取i的值,然后在进行加1操作,最后对i进行赋值,这里就进行了4个步骤,如果在第2个步骤的时候另外一个线程也来进行了i++操作,那么可想而知最终得到的结果可能就不是自己想要的了。那么我们如何保证i++的原子操作呢?这个时候肯定大家也能想到用同步啊,synchronized关键字和Lock锁都可以进行同步的控制,当然这也是正确的,但是我们今天所说的多线程原子操作是通过jdk提供的JUC包实现的原子操作,如AtomicInteger,AtomicReference等原子操作类,在JUC包中的原子类操作基本都实现了CAS(compare and swap)操作,当对某个值进行改变时CAS会先对当前值进行比较,如果正确才进行值的交换即更新值,CAS操作是在硬件资源上直接进行的操作,是由处理器提供的内存操作指令,由其保证原子性。通过查看相关的JUC包,可以看到很多Unsafe类方法的使用,这个类提供了很多native方法的使用,因为是不安全的类,所以自己想使用的话,必须自己去通过反射进行获取来进行操作。
虽然说JUC包提供了很多原子的CAS操作,但是它一次只能针对一个变量进行CAS操作,不能进行多个变量的操作,同时因为要不停的进行CAS的判断和交换值操作,所以线程会一直处于高频的运行中,如果其中一个线程处理时间过长,那么就会带来CPU的高性能消耗,同时CAS操作还会出现一种叫做ABA的问题,即当前值是A,将它换做B,然后又由B换做A,那么就无法判断A是否在这期间发生过变化,因为最终值没有变化,如果在AB的时候有其他线程来进行了操作A操作,而该线程在休眠时间内又从B变回了A,而此时A的指向已经发生改变,那这种改变带来的结果是其他线程对A的操作已经发生改变,得到的结果也可能发生变化,那么怎么来解决这个ABA的问题呢?我们可以采用类似版本号的控制机制来实现避免ABA这种问题,在JUC包中提供了AtomicStampedReference类,它提供了一个版本控制的判断,我们使用以下代码运行后可以看到不同的结果
public class AtomicStampedReferenceTest { public static void main(String [] args){ AtomicStampedReference reference = new AtomicStampedReference(0,0); new Thread(() ->{ reference.compareAndSet(0,1,0,1); System.out.println(reference.getReference() + "--->" + reference.getStamp()); }).start(); new Thread(() ->{ reference.compareAndSet(0,1,1,2); System.out.println(reference.getReference() + "--->" + reference.getStamp()); }).start(); new Thread(() ->{ reference.compareAndSet(1,2,1,2); System.out.println(reference.getReference() + "--->" + reference.getStamp()); }).start(); }
相关推荐
在Java多线程编程中,原子操作是一种非常关键的概念,它涉及到并发控制和线程安全。原子操作是指在不被其他线程中断的情况下,能够完整执行的一个或一系列操作。这样的操作在多线程环境中可以保证数据的一致性和完整...
Java多线程编程中,原子性、可见...总结来说,原子性、可见性和有序性是Java多线程编程中保证并发安全的重要概念。通过合理使用Java提供的并发工具和关键字,开发者可以有效地管理线程之间的交互,确保程序的正确运行。
Java多线程是Java编程中的一个重要概念,它允许程序同时执行多个任务,提高了程序的效率和响应速度。在Java中,实现多线程有两种主要方式:继承Thread类和实现Runnable接口。 1. 继承Thread类: 当我们创建一个新...
Java多线程是Java编程语言中一个非常重要的概念,它允许开发者在一个程序中创建多个执行线程并行运行,以提高程序的执行效率和响应速度。在Java中,线程的生命周期包含五个基本状态,分别是新建状态(New)、就绪...
Java多线程是Java编程中的重要概念,尤其在如今的多核处理器环境下,理解并熟练掌握多线程技术对于提高程序性能和响应速度至关重要。本资料详细讲解了Java多线程的原理,并提供了丰富的实战代码,非常适合Java初学者...
- volatile:修饰变量,确保多线程环境下的可见性和有序性,但不保证原子性。在实例中,可能用于共享标志的设置与读取。 - wait()、notify()和notifyAll():这些方法存在于Object类中,用于线程间的通信。在线程A...
Java多线程编程是Java开发中的重要组成部分,它允许程序同时执行多个任务,极大地提高了程序的效率和响应性。在Java中,多线程主要通过继承Thread类或实现Runnable接口来实现。本教程《Java多线程编程核心技术》将...
5. 原子操作(Atomic):AtomicInteger、AtomicLong等原子类提供了无锁编程的支持,保证了在多线程环境下的原子性操作。 总结,Java多线程设计是构建高性能、高并发应用的基础。通过理解并合理使用不可变对象,我们...
《Java多线程编程实战指南-核心篇》是一本深入探讨Java并发编程的书籍,旨在帮助读者掌握在Java环境中创建、管理和同步线程的核心技术。Java的多线程能力是其强大之处,使得开发者能够在同一时间执行多个任务,提高...
Java多线程同步是Java编程中关键的并发概念,它涉及到如何在多个线程访问共享资源时保持数据的一致性和完整性。`java.util.concurrent`包是Java提供的一个强大的并发工具库,它为开发者提供了多种线程安全的工具,...
原子性操作(如AtomicInteger)则可以保证在多线程环境下的原子性。 6. 线程中断与守护线程 Thread类提供了interrupt()方法用于中断线程,但需要注意的是,这并不意味着线程会立即停止,而是在线程检查到中断标志后...
Java多线程是Java编程中的核心概念,它允许程序同时执行多个任务,提高了系统的效率和响应性。在Java中,多线程的实现主要通过两种方式:继承Thread类和实现Runnable接口。理解并掌握多线程的使用对于任何Java开发者...
Java多线程编程是Java开发中的重要组成部分,它允许程序同时执行多个任务,极大地提高了程序的效率和响应性。在Java中,多线程主要通过继承Thread类或实现Runnable接口来实现。本教程将深入探讨Java多线程的各个方面...
总的来说,这个项目涵盖了Java多线程编程中的诸多重要知识点,包括线程创建与管理、并发控制、异常处理、事务一致性以及测试。通过实际操作,开发者可以深入理解并掌握这些关键概念和技术,提升自己的编程能力。
Java多线程是Java编程中一个非常重要的概念,它允许程序在同一时间执行多个任务,从而提高了应用程序的效率和响应速度。在操作系统中,程序被加载到内存中形成进程,而进程中的执行单元就是线程。Java多线程的实现...
通过学习《Java多线程编程实战指南》,开发者不仅可以理解多线程的基本概念,还能掌握如何在实际项目中运用多线程技术,提升程序的并发性能和稳定性。无论是初级开发者还是经验丰富的工程师,这本书都是一本值得阅读...
Java多线程是Java编程中的重要概念,它允许程序同时执行多个任务,从而提升系统效率。在多线程环境中,变量共享是一个常见的需求,但也是引发问题的关键点。本篇文章将深入探讨Java多线程下变量共享的问题以及解决...
Java多线程是Java编程中的核心部分,尤其在现代高性能应用和分布式系统中不可或缺。理解并掌握Java多线程能够提升程序的效率、响应速度以及资源利用率。 本书可能涵盖了以下几个重要的知识点: 1. **线程基础**:...
Java中的`AtomicIntegerArray`是`java.util.concurrent.atomic`包中的一个类,它提供了一种在多线程环境下原子性地更新整型数组元素的方法。这个类和其他两个类似类——`AtomicLongArray`(用于原子更新长整型数组)...
java多线程安全性基础介绍 线程安全 正确性 什么是线程安全性 原子性 竞态条件 i++ 读i ++ 值写回i 可见性 JMM 由于cpu和内存加载速度的差距,在两者之间增加了多级缓存导致,内存并不能直接对cpu可见。 ...