java并发编程(一) 入门篇----为什么要使用并发编程

一. 为什么要使用并发编程?

并发编程的主要目的是为了使程序运行的更快;

但是下一个问题出来了,并发编程一定会使我们的程序运行的更快吗?为什么并发编程会使我们的程序变得更快呢?

二. 理解并发编程

2.1并发编程一定会使我们的程序运行的更快吗?

答案是并不是,并发编程只有在一定的请求量或者计算量的时候才会显示出优势;

2.2 为什么有的时候多线程反而会变慢呢?

我们知道os(操作系统)执行并发操作是采用的时间片轮转算法,简单的说就是线程1先执行10ms 然后线程B在执行10ms 然后线程A又执行了10ms 线程A执行完毕 线程B又开始执行到结束

我们可以发现这种执行的机制,会导致cpu一会执行A线程 一会执行B线程,这就导出了一个第一个导致多线程慢的因素:线程的上下文切花需要时间
补充:Java创建多线程需要OS的干预,OS需要从用户态切换到核心态 这个过程很耗费时间

那么简单的理解就是:如果多线程执行的速度快于单线程执行的速度,那么我们可以理解为多线程一定会在执行前做一些准备,而单线程不需要,所以当任务数或者工作量并不大的时候单线程就会很有优势;但是当任务数上来后多线程的优势就体现出来了;
这里我们有个可以继续深入研究的点:即具体什么时候,什么情况下单线程执行优于多线程

2.3 那么如何提高并发编程的性能呢?

我们知道并发性能的瓶颈就是频繁的上下文切换,那么我们就可以通过减少上下文的切换来提高性能。

减少上下文切换的方法又一下几种

1. 采用无锁并发编程:多线程竞争锁的时候就会引起上下文的切换,所以处理数据的时候应该避免加锁,可以把数据分段,每个线程来处理一段的数据,
2. CAS算法: Java的Atomic包使用CAS算法来更新数据,不需要加锁

**3. 尽量合理的配置线程即使用最少的线程:**例如我们处理一个任务10个线程100ms搞定,那么你开100000个线程来处理,光上下文切换的时间都要超过100ms

**4. 使用协程:**在单线程里实现任务的调度,并在单线程里维持多个任务的切换

2.2 为什么并发编程会使我们的程序变得更快呢?

首先对于单线程来说,程序是一行一行的执行的,所以假设在120行-180行之间的程序含有数据库操作需要等待很长时间,那么180行以后的代码都必须等到180行的代码执行完才能继续执行,而并发编程其实就是异步化,也就是主线程在执行到120行的时候,120-180行的代码交给另一个线程去执行,主线程可以继续向下执行,所以两件事是并行的,所以程序的响应时间就会变快

三.死锁

死锁是导致系统功能不可用的重要原因之一;
什么是死锁呢?
线程1在等待线程2释放锁,线程2也在等线程1释放另一个锁,最终导致线程1和2都在等待中,从而不能继续执行程序;

构成死锁的必要条件有一下几个

  1. 互斥
  2. 不可剥夺
  3. 保持申请
  4. 循环等待
    互斥:也就是加互斥锁,线程1获取到了对资源1的锁,那么线程2就不能获取对资源1的锁了
    不可剥夺 线程1对资源1加的锁,线程2不可以撤销线程1对资源1加的锁
    保持申请 线程1一直持有对资源1的锁
    循环等待 线程1等线程2 线程2等线程1
代码行线程1的操作线程2 的操作
100行对资源1加锁其他操作
110行执行其他操作对资源2加锁
120行获取资源2 因为有锁所以等待获取资源1 因为有锁所以等待
121行因为线程在等待 所以此行不会执行因为线程在等待 所以此行不会执行

我们可以看到线程1和2都在120行处等待,所以下面的代码不会执行, 这就是死锁

3.1 如何避免死锁呢?
  1. 避免一个线程同时获取多个锁
  2. 避免一个线程同时占用多个资源
  3. 尝试使用定时锁来代替内部的锁机制
  4. 对于数据库锁,加锁和解锁必须在同一个连接内,否则解锁会失败

四.多线程需要考虑的问题

即使我们使用了多线程,但是系统还是会受到硬盘的读写速度,网络带宽,cpu处理速度等的影响
所以在设置线程数的时候也要综合考虑

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值