
课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
并发编程开发是Java编程开发程序员在开发软件的时候会经常遇到的一个编程开发需求,而本文我们就通过案例分享来简单了解一下,并发编程开发都有哪些常见问题。
1、多线程引起的问题
使用多线程会引发并发问题,如果多个线程对同一个共享数据进行访问而不采取同步操作的话,那么操作的结果是不一致的。
出现的根源就是CPU、内存、I/O设备的速度是有极大差异的,为了合理利用CPU的高性能,平衡这三者的速度差异,计算机体系结构、操作系统、编译程序都做出了贡献,主要体现为:
CPU增加了缓存,以均衡与内存的速度差异;//导致可见性问题
操作系统增加了进程、线程,以分时复用CPU,进而均衡CPU与I/O设备的速度差异;//导致原子性问题
编译程序优化指令执行次序,使得缓存能够得到更加合理地利用。//导致有序性问题
可见性、原子性、有序性即为并发三要素,张三取钱没有同步到账上,也就是可见性问题。
在执行程序时为了提高性能,编译器和处理器常常会对指令做重排序。重排序分三种类型:
编译器优化的重排序。编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序。
指令级并行的重排序。现代处理器采用了指令级并行技术(Instruction-LevelParallelism,ILP)来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。
内存系统的重排序。由于处理器使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是在乱序执行。
2、JAVA是怎么解决并发问题的
既然多线程存在这三个问题,那么Java就需要解决这三个问题。
针对原子性,Java内存模型只保证了基本读取和赋值是原子性操作,如果要实现更大粒度的原子性,可以通过synchronized和Lock来实现。
针对可见性,Java提供了volatile关键字来保证可见性。当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值。,通过synchronized和Lock也能够保证可见性,synchronized和Lock能保证同一时刻只有一个线程获取锁然后执行同步代码,并且在释放锁之前会将对变量的修改刷新到主存当中。
针对有序性,使用先行发生原则(happens-before),让一个操作无需控制就能先于另一个操作完成。
3、怎么避免并发问题呢?
不可变(Immutable)的对象一定是线程安全的,不需要再采取任何的线程安全保障措施。只要一个不可变的对象被正确地构建出来,永远也不会看到它在多个线程之中处于不一致的状态。
多线程环境下,应当尽量使对象成为不可变,来满足线程安全。
Number部分子类,如Long和Double等数值包装类型,BigInteger和BigDecimal等大数据类型。但同为Number的原子类AtomicInteger和AtomicLong则是可变的。
对于集合类型,可以使用Collections.unmodifiableXXX()方法来获取一个不可变的集合。
【免责声明】:本内容转载于网络,转载目的在于传递信息。文章内容为作者个人意见,本平台对文中陈述、观点保持中立,不对所包含内容的准确性、可靠性与完整性提供形式地保证。请读者仅作参考。更多内容请加danei0707学习了解。欢迎关注“达内在线”参与分销,赚更多好礼。