Java高效并发

一段时间没有回顾多线程相关知识了,虽然工作中会用到一些多线程的内容,但都偏向于基础,今天重读多线程相关内容,发现有些东西还是需要注意下。这些一般是面试高频问题奥。

了解并发的内幕是一个高级程序员不可缺少的课程

Java内存模型

注意,Java内存模型(JMM)和JVM运行时数据区不是同一个概念,还有一个概念是Java对象模型下次可以单独拿出来说。

  • JMM都是围绕着原子性,可见性,有序性来讲的
  • JMM定义了JVM如何与计算机的内存进行交互

线程对变量的所有操作都需要在工作内存中完成,不可直接操作主内存。

内存间的交互操作:
Lock,Unlock 主内存
Read,Write 主内存
Load,Store 工作内存的变量
Use,Assign 工作内存的变量

更多关于JMM的信息查看,多线程之Java内存模型

Volatile

Volatile可以说是Java虚拟机内提供的最轻量级同步机制,其只保证,可见性与有序性,不保证原子性。

可见性:当一条线程修改了这个变量的值,新值对于其他线程来说是可以立刻得知的,另外两个可以实现可见性的关键字:Synchronizedfinal

有序性:如果再本线程内观察,所有的操作都是有序的,如果再一个线程中观察另外一个线程,那么所有的操作都是无序的。

Java与线程

并发不一定依赖多线程,如PHP中常见的多进程并发。Java的Thread类所有关键方法都是声明为Native的,所以Java并没有自己实现线程。

实现线程的三种方式:使用内核线程实现,使用用户线程实现,和使用用户线程加更加轻量级进程实现。

  1. 内核线程实现(KLT,Kernel-Level Thread)。程序一般不会直接使用内核线程,而是使用内核线程的一种高级接口,轻量级进程(LWP,Light Weight Process,LWP),先有内核线程,才能有轻量级进程。

缺点:各种线程操作,如创建,析构,及同步需要进行系统调用,而系统调用的代价比较高,需要在用户态和内核态中来回切换。消耗内核资源,一个系统支持轻量级的进程数量是有限制的。

  1. 用户线程实现,广义上说,一个线程只要不是内核线程,那就可以任务是用户线程。用户线程完全在用户态完成,不用内核的帮助,可以支持更大的线程数量。

缺点:没有内核支持,各种操作都比较复杂。现在基本弃用了。

  1. 用户线程 + 轻量级进程,综合两者的有点,用户进程与轻量级进程数量比是不定的。

线程调度

协同式调度:好处是实现简单,切换操作对线程自己是可知的,没有线程同步的问题,线程把自己的事情干完之后才进行线程切换。

缺点:如果程序编写不稳定,那么系统不可控制。一个进程坚持不让出CPU执行实现,就会导致系统崩溃。

抢占式调度(Java默认调度):每个线程由系统来分配执行和弦,线程的切换不由线程来决定,当一个进程出现问题,系统可以杀掉这个进程。

注意:并不是线程的优先级越高,线程就一定会优先执行,只是说优先级高的线程更可能被选择到。

Java线程状态转换

贴一张图,好好记:

线程安全的实现方法

  • 互斥同步,加锁,悲观方案,保证共享数据同一时刻只有一个线程访问。,互斥是因,同步是果。
  • 非阻塞同步,CAS,乐观方案,先进行操作,如果没有其他线程也进行操作,那么就操作成功了,如果有其它线程也在操作共享数据,那么再重试。
  • 无同步方案,一般为纯代码,有一些特性,如不依赖堆上的公用系统资源

锁优化

  • 自旋锁与自适应自旋
    假如共享数据只会持续很短的一段时间,为了这段时间进行挂起和恢复线程并不值得,这时我们可以让后面请求锁的线程稍等一下,让线程进行一个忙循环(自旋),这就是所谓的自旋锁。

因为们有时不值得共享数据到底被锁了多久,盲目的自旋可能导致性能的损失,JDK1.6之后,系统引入了自适应的自旋,及在一次共享数据被锁定时,加入系统多次获得自旋锁,系统可以允许线程自旋的次数更多时间更久一些。如果多次没有获得自旋锁,那么系统下次可能会省略掉自旋锁。

  • 锁消除
    对一些不可能存在共享数据竞争的锁进行消除。
  • 锁粗化
    有时候多个操作都对同一个对象加锁,频繁的加锁也会影响性能,那么系统就把锁的同步范围进行扩展。如StringBuffer()的多个append操作。
  • 偏向锁
    可以理解为偏袒锁,锁会偏向于第一个获得它的线程,如果接下来的执行过程中,该锁没有被其他线程获取,则持有偏向锁的线程将永远不在需要进行同步。

最后

了解并发的内幕是一个高级程序员不可缺少的课程

参考

  • 《深入理解JVM》

原文地址:http://blog.51cto.com/amyhehe/2134648

时间: 2024-11-02 18:43:08

Java高效并发的相关文章

Java 高效并发

Java 高效并发 为了便于移植,Java 多线程内存模型不与硬件关联,不同硬件平台可以使用不同的实现手段 和 CPU 内存与高速缓存做对比 Java 内存模型被分为两大部分:主内存(对应 PC 内存)和工作内存(对应 CPU 高速缓存) 主内存与工作内存之间数据的交互 Java 定义了以下 8 种原子操作(最新的 Java 标准已经采用了新的内存访问协议,但下面 8 中操作也应该了解一下) lock,标识主内存变量为线程独占 同一个变量可以被一条线程多次 lock,但也需要同样次数的 unlo

Java高并发秒杀API之业务分析与DAO层

课程介绍 高并发和秒杀都是当今的热门词汇,如何使用Java框架实现高并发秒杀API是该系列课程要研究的内容.秒杀系列课程分为四门,本门课程是第一门,主要对秒杀业务进行分析设计,以及DAO层的实现.课程中使用了流行的框架组合SpringMVC+Spring+MyBatis,还等什么,赶快来加入吧! 第1章 课程介绍 本章介绍秒杀系统的技术内容,以及系统演示.并介绍不同程度的学员可以学到什么内容. 第2章 梳理所有技术和搭建工程 本章首先介绍秒杀系统所用框架和技术点,然后介绍如何基于maven搭建项

Java 多线程并发编程面试笔录一览

知识体系图: 1.线程是什么? 线程是进程中独立运行的子任务. 2.创建线程的方式 方式一:将类声明为 Thread 的子类.该子类应重写 Thread 类的 run 方法 方式二:声明实现 Runnable 接口的类.该类然后实现 run 方法 推荐方式二,因为接口方式比继承方式更灵活,也减少程序间的耦合. 3.获取当前线程信息? Thread.currentThread() 4.线程的分类 线程分为守护线程.用户线程.线程初始化默认为用户线程. setDaemon(true) 将该线程标记为

Java高并发程序设计

一.并行世界 摩尔定律的失效,2004年秋季,Intel宣布彻底取消4GHz计划,CPU向多核心的发展,顶级计算机科学家唐纳德丶尔文丶克努斯评价:在我看来,这种现象(并发)或多或少是由于硬件设计者已经无计可施导致的,他们将摩尔定律失效的责任推脱给软件开发者. 1.几个概念 同步和异步: 并发与并行:都表示多个任务同时执行,但并发偏重于多个任务交替执行. 临界区:即共享的数据 阻塞和非阻塞: 死锁.饥饿和活锁:死锁为互不让行,饥饿为一直拿不到资源,活锁为一直撞到 2.并发级别   由于临界区的存在

Java:并发不易,先学会用

我从事Java编程已经11年了,绝对是个老兵:但对于Java并发编程,我只能算是个新兵蛋子.我说这话估计要遭到某些高手的冷嘲热讽,但我并不感到害怕. 因为我知道,每年都会有很多很多的新人要加入Java编程的大军,他们对"并发"编程中遇到的问题也会有感到无助的时候.而我,非常乐意与他们一道,对使用Java线程进行并发程序开发的基础知识进行新一轮的学习. 本篇我们来谈谈 Java 并发编程:并发编程并不容易掌握,但很有必要掌握. 01.我们为什么要学习并发? 我的脑袋没有被如来佛祖开过光,

高效并发(四)

前言 ? ? ? ?上篇已经分析了lock和concurrent提供的集合类包括阻塞队列和容器类.这里我们来介绍 Executor框架 线程池的作用 ? ? ? ?线程池作用就是限制系统中执行线程的数量.根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果:少了浪费了系统资源,多了造成系统拥挤效率不高.用线程池控制线程数量,其他线程 排队等候.一个任务执行完毕,再从队列的中取最前面的任务开始执行.若队列中没有等待进程,线程池的这一资源处于等待.当一个新任务需要运行时,如果线程 池中

2017.4.26 慕课网--Java 高并发秒杀API(一)

Java高并发秒杀API系列(一) -----------------业务分析及Dao层 第一章 课程介绍 1.1 内容介绍及业务分析 (1)课程内容 1 SSM框架的整合使用 2 秒杀类系统需求理解和实现 3 常用技术解决高并发问题 (2)SSM框架 (3)为何选择秒杀系统 1 秒杀系统具有典型的"事务"特性 2 秒杀/红包类需求越来越常见 3 面试常用问题 1.3 项目效果演示 第二章 梳理所有技术和搭建工程 2.1 相关技术介绍 2.2 创建项目和依赖 第三章 秒杀业务分析 3.

Java高效读取大文件

1.概述 本教程将演示如何用Java高效地读取大文件.这篇文章是Baeldung (http://www.baeldung.com/) 上“Java——回归基础”系列教程的一部分. 2.在内存中读取 读取文件行的标准方式是在内存中读取,Guava 和Apache Commons IO都提供了如下所示快速读取文件行的方法: Files.readLines(new File(path), Charsets.UTF_8); FileUtils.readLines(new File(path)); 这种

Java IO: 并发IO

原文链接 作者: Jakob Jenkov 译者: 李璟 有时候你可能需要并发地处理输入和输出.换句话说,你可能有超过一个线程处理输入和产生输出.比如,你有一个程序需要处理磁盘上的大量文件,这个任务可以通过并发操作提高性能.又比如,你有一个web服务器或者聊天服务器,接收许多连接和请求,这些任务都可以通过并发获得性能的提升. 如果你需要并发处理IO,这里有几个问题可能需要注意一下: 在同一时刻不能有多个线程同时从InputStream或者Reader中读取数据,也不能同时往OutputStrea