并发编程学习—— 1 概述

为什么要使用多线程

硬件的支持

目前CPU都已经是多核心的情况下。假如程序只在一个线程运行的时候,就无法完全利用多核心的好处,而且单线程中等待IO的操作会带来大量的等待时间,所以在目前多核心CPU普及的情况下,多线程成为更好的解决方案

为了更灵敏的响应

在单线程执行的时候,当前一个请求没有完成请求的情况下,后一个请求是无法处理的。假如因为资源获取产生延迟会导致后面请求都阻塞那里。而在多线程的情况下,当前一个请求因为前一个请求因为资源阻塞的话,这个请求依然可以进行自己的业务。而用户的体验就会好很多

多线程的风险

事物总是存在两面性,既然有好的地方,肯定也有其不好的一方面。

安全问题

多线程中线程的操作顺序是不可预测的,错误的代码在多线程的环境下,会产生一些不可预测的结果。

public class ErrorThread {

    private static UnsafeSequence obj = null;

    private static UnsafeSequence getObject () {
        if (obj == null) {
            obj = new UnsafeSequence();
        }
        return obj;
    }
}

比如上面就可能存在多线程情况下多个线程重复创建对象而产生的问题。当然这个例子无非重复创建对象,无非浪费了系统资源,目前看不到来什么问题。

像是下面情况就不美了

   private static int stock = 100;


    private static int sale () {
        if (stock > 0) {
            try {
                // 模拟业务逻辑
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            stock = stock - 1;
            System.out.println(stock);
            return stock;
        }
        return -100;
    }

假如这个时候我们在卖东西,多条线程去请求库存,此时多个线程都尝试拿库存没有妥善的并发编程最终导致出现超卖的情况也是很容易出现的。

死锁

多个线程互相持有其他线程需要的资源的时候,可能导致双方都进行阻塞,然后系统卡死出现死锁

public class DeadLockTest {

    private Object one = new Object();

    private Object two = new Object();

    public void getOne () {
        synchronized (one) {
            synchronized (two) {
                //doSame
            }
        }
    }

    public void getTwo () {
        synchronized (two) {
            synchronized (one) {
                //doSame
            }
        }
    }
}

上面就是一个很典型的死锁代码。当然我想只要稍微有点水平的同学都不会写成这个样子。但是很多时候获取锁并不像上面例子那么明显,这两个锁并不一定必须在同一个方法中获取。有的时候方法持有锁的时候尝试调用外部方法,假如这个方法需要持有另外一个锁,或者这个方法阻塞时间过长。都可能导致其他线程无法及时获得当前被持有的锁。

资源死锁

死锁不仅仅指的是代码上的死锁,除了多个线程互相持有彼此时会发生死锁,当它们在相同的资源集合上等待时也会发生死锁。这种死锁比代码上的死锁可能更难排查。

额外的性能开销

多线程中,线程调度器临时挂起活跃线程而运行另一个线程时,就会频繁地出现上下文切换操作,这种操作会带来极大的开销。当线程共享数据时,必须使用同步机制,而这些机制可能会和编译器优化冲突。

高昂的代价

JVM在解决死锁问题时,当一组Java线程发生死锁时,这些线程永远不能再使用了。可能造成应用程序完全停止或者某个特定的子系统停止,或者性能降低。恢复应用程序的唯一方式就是中止并重启它。

更高的技术要求

通常单线程编程的时候,只要我们保证代码的正确。业务逻辑没有错误一般不会出现严重的问题。而多线程情况下,很多时候问题在低并发情况下并不容易发现。而在没有足够的了解并发原理的情况下,即使出现了错误也很难排查出问题。

多线程涉及的内容

这是目前针对多线程可能涉及的内容,也是个人学习整理的笔记内容

线程的安全性

上面说了线程存在这么多问题,那么线程的安全性就是总结如何去避免出现上面问题。

  1. 在保证线程安全之前,首先要明确什么是线程安全。
  2. 线程安全性出现了哪些问题。
  3. 如何来保证线程的安全。

队列

  1. Queue
  2. BlockingQueue
  3. Deque

线程安全的类/同步容器类

主要是JDK提供的容器工具

  1. 同步容器
  2. 并发容器

线程/线程池

主要是介绍更加合理的线程使用方式

  1. 线程池的参数配置
  2. 线程池的使用
  3. 线程的使用

线程-锁

主要介绍JAVA 内置锁和后续添加的Lock工具

  1. 锁的介绍、内置锁和Lock
  2. 锁的使用

多线程影响性能的因素

从来没有白吃的午餐,多线程提高性能的同时也在消耗着系统的资源。

  1. 影响性能的因素
  2. 如果减少性能消耗
  3. 硬件或者系统上的处理
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大·风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值