栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

「Java」「并发编程」一看入门

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

「Java」「并发编程」一看入门

摘要】 在Java中并发就是指多线程的进程环境,进程是系统进行资源分配和调度的独立单位,每一个进程都有它的内存空间和系统资源,在同一个进程内执行的多个任务就可以看作是多个进程,线程存在于进程内,进程负责分配调度线程,线程负责执行程序,多个线程就执行多个程序

一、基本简介

什么是并发

在Java中并发就是指多线程的进程环境,进程是系统进行资源分配和调度的独立单位,每一个进程都有它的内存空间和系统资源,在同一个进程内执行的多个任务就可以看作是多个进程,线程存在于进程内,进程负责分配调度线程,线程负责执行程序,多个线程就执行多个程序。

实际上,Java程序天生就是一个多线程程序,包含了:

分发处理发送给JVM信号的线程调用对象的finalize清除方法的线程清除相互引用reference的线程main线程,也就是用户程序的入口,main线程里面还可以拥有很多的子线程

为什么需要多线程

如果没有多线程,若为了使程序并发执行,那么系统需要花费大量的时间在:创建进程-->撤销进程-->进程上下文切换调度,在这一过程中,需要的空间开销也非常大,执行效率也非常低(如下图);若在一个进程中执行多个线程,则上面的空间开销和时间花费将会大大较少,何乐而不为呢,多线程提高了系统的执行效率,充分利用多核CPU的计算能力,提高应用性能。

二、并发编程带来的问题

频繁的上下文切换问题

正如上图中的时间片,时间片使CPU分配给各个线程的时间,因为时间非常短,所以CPU需要不断切换线程,让我们觉得多个线程是同时执行的,时间片一般是十几毫秒;每次切换都需要保存当前线程的状态,以便进行恢复先前的状态。这个切换是非常耗性能的,过于频繁就无法发挥出多线程编程的优势了。那么该怎么解决这频繁的上下文切换的问题的,目前有大概几种解决方法,后面会详细讨论:

采用无锁并发编程:JDK8以前的concurrentHashMap采用的锁分段思想,不同线程处理不同段的数据,这样在多线程环境下可以减少上下文的切换时间。采用CAS算法:JDK8以后的concurrentHashMap采用的是无锁CAS算法;利用Atomic和乐观锁,可以减少一部分不必要的锁竞争带来的上下文切换。尽量减少线程的使用:避免创建不需要的线程,比如任务少,但是创建了很多的线程,这样会造成大量的线程都处于等待状态。采用协程:在单线程里实现多任务的调度,并在单线程里维持多个任务间的切换。

因此,并发累加未必会比串行累加的速度快,这上下文切换的问题在实际中是需要解决的。

线程安全问题(主要问题,也是我们程序开发关心的问题)

对线程编程中最难控制的就是临界区(共享内存的地方)的线程安全问题,稍微不注意就会出现死锁的情况,一旦产生死锁就会造成系统功能不可用。那么怎么解决这种问题呢,解决方法如下:

避免一个线程同时获取多个锁避免一个线程在锁内部占用多个资源,尽量保证一个锁只占用一个资源尝试使用定时锁,如使用lock.tryLock(timeOut),当超时等待时当前线程也不会阻塞对于数据库锁,加锁和解锁必须在同一个数据库连接里(同一个事务),否则会出现解锁失败的情况

后面还有JMM内存模型在原子性、有序性和可见性带来的问题,比如数据脏读,内存泄漏等等问题,这是又该如何保证线程安全呢,这一方面是非常重要的,后面会详细讨论。

三、并发编程的相关概念

同步和异步

同步和异步通常用来形容方法的一次调用。

同步方法从被调用开始,调用者就必须等待被调用的方法结束后,调用好后面的代码才能继续执行。

异步方法指的是,调用者不管被调用的方法是否完成,都会继续执行后面的代码,当被调用的方法完成后会通知调用者。

并发和并行

并发是指多个任务线程交替进行的。

并行是指真正意义上的“同时进行”。

实际上,如果系统只有一个CPU,而使用多线程时,那么真实环境下时不能并行执行的,只能通过切换时间片的方式交替进行,完成并发执行任务,真正的并行只能出现在拥有多个CPU系统中。

阻塞和非阻塞

阻塞和非阻塞通常用来形容多线程间的相互影响。

阻塞是指如果一个线程占用了临界区的资源,那么其他线程需要这个资源的话就必须等待资源的释放,就会导致等待的线程挂起,这种情况就叫做阻塞。

非阻塞刚好跟阻塞相反,它强调的是没有一个线程可以阻塞其他线程,所有的线程都会尝试的向前运行。

临界区

临界区用来表示一种公共资源会共享数据,可以被多个线程使用,出于线程安全问题,如果一个线程占用了临界区的资源,那么其他线程就必须等待,知道临界区的资源被释放。

守护线程

守护线程是一种特殊的线程,是系统的服务线程,是专门为其他线程服务的,像垃圾回收线程就是守护线程,与之对应的是用户线程,用户线程作为系统的工作线程,守护线程的服务对象就是用户线程,当全部的用户线程执行任务完成之后,这个系统就没有什么需要服务的了,那么守护线程就没有对象需要守护了,那么守护线程就会结束,也就是说当一个java程序只有守护线程的时候,虚拟机就会退出了。

四、Java中的线程Thread类

参考看一下Thread类的源码注释,了解Java中的线程:

 
五、总结 

我们需要了解并发,为什么需要并发,还必须知道并发的优缺点,同时清楚使用并发编程之后所带来的问题:频繁上下文切换问题和线程安全问题等等,后面在并发编程的时候就朝着这些问题去编程,尝试解决这些问题,让并发编程发挥出真正的作用。

理解Java并发的关键点在于理解它的两大核心(JMM内存模型【工作内存和主内存】和happes-before规则【八大规则】)以及三大特性:原子性、可见性、有序性

如果感觉小编写得不错,请素质三连:点赞+转发+关注。我会努力写出更好的作品分享给大家。更多JAVA进阶学习资料小编已打包好,可以关注私信找我领取哦!

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/777875.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号