Java并发编程

0.背景

1.为什么会有并发编程的概念呢?

因为硬件的发展,多核CPU的出现,为了更充分地利用多核CPU,可以让任务在多个核上并行地计算,以提升程序的计算效率

2.应用场景:

如GUI程序,提升响应用户的速度;

如服务端 同时响应多个客户端请求,提升吞吐量和响应。

异步事件的简化处理

3.引入并发编程导致了哪些问题?

(1)线程安全问题 

由于多个线程并发地访问线程共享的状态,如业务数据,数据缓存,数据库连接池等,可能会发生丢失更新的情况。

什么样的类是线程安全的呢?

(2)活跃性问题

当线程之间发生死锁,可能导致线程都阻塞,任务无法继续下去

(3)性能问题

线程之间的互相阻塞等待将会丢失部分并行性,内核线程的上下文切换、内存同步都有开销,导致性能的下降。

4.如何分辨一个对象是否线程安全?

  1. 无状态的对象一定是线程安全的。

5.怎样修复线程安全问题呢?

  1. 线程之间不共享该状态变量 ThreadLocal
  2. 将状态变量修改为不可变变量 final 如String
  3. 访问时 同步 synchronized

1.分工

使用多个线程并行处理子任务,使得大任务能够高效完成。

1.1 实现方法

1.1.1 创建线程

有3中方式创建线程,实现Runnable接口、实现Callable接口和继承Thread类,通常使用实现Runnable接口的方式

    @Test
    public void testStart() {
        Thread B = new Thread(new Runnable() {
            public void run() {
                ......
            }
        });
        // 主线程启动子线程
        B.start();
    }

 start()方法启动线程,线程状态流转如下图所示

1.1.2 线程池

管理工作线程的池子,具体请见

ThreadPoolExecutor

构造参数

参数名称含义作用
corePoolSize基本大小-初始
maximumPoolSiz

最大线程数

在workQueue满时创建新线程

keepAliveTime

最大空闲存活时间

空闲超过这个时间,销毁线程 小与基本大小

unit时间单位
workQueue工作队列,存放任务

2.同步互斥

从上述引发的问题总结而言有以下3个需求需要解决:

  1. 有序性   CPU会进行编译优化指令,在不可预见的线程调度下,可能发生跟预期结果不一致
  2. 可见性   各个线程会将共享变量加载进自己的工作内存,可能不能实时看见别的线程修改了共享变量
  3. 原子性   有的几步操作不能被中断 ,但是中途线程切换了导致状态有问题

多个工作线程协同完成一个大任务,就像我们跟同事协同开发同一个分支,为了避免重复性劳动或者代码覆盖、或者阻塞等待的问题,我们需要及时地同步状态和进度,工作线程也需要。

2.1 同步互斥

其实就是将某部分代码从并发执行 改为 串行执行,从而避免并发执行可能引起的竞态问题。

2.1.1 synchronized

最简单的方式就是加上synchronized关键字,这是Java内置互斥重入锁。

public class SynchronizeExample {
    private int x;
    //同步块
    public void synBlock(){
        synchronized (this) { // 此处自动加锁
            // x 是共享变量, 初始值 =10
            if (this.x < 12) {
                this.x = 12;
            }
        } // 此处自动解锁
        // 规则4 一个锁的解锁 Happens-Before 于后续对这个锁的加锁
    }
}

为什么也被称为对象锁(普通对象或者Class对象)呢?因为是CAS操作对象头实现互斥的,每个对象都有对象头和实例数据,对象头包含Mark Word和元数据指针,Mark Word中标记了该对象的锁状态,当对象处于偏向锁状态时保存了持有该对象的线程id,除了该线程可以重入该对象的所有同步块,其余对象都需要等待。synchronized实现https://www.jianshu.com/p/e2054351bd95

锁升级过程

2.1.2 ReentrantLock

除了synchronized之外,还可以用java.util.concurrent包里的ReentrantLock来同步,都是可以可重入互斥锁,是通过AQS实现的API层面的,比synchronized多了一些高级功能,如等待锁时是可以被中断的、可以传递参数实现公平锁、可以绑定多个条件Condition。

        Lock lock = new ReentrantLock();
        lock.lock();
        try {
            //.....
        } finally {
            lock.unlock();
        }

3.协作

3.1 线程通信协作方式

在一些线程并发执行时,需要依赖别的线程操作,就像我们工作过程中要做工作B得等同事先把A做完,我们要一直阻塞等到同事告诉我们A已经完成,我们才被唤醒开始做B。此时两个线程需要通信,由于线程之间是共享主存的,而对象就存储在主存中,可以借助对象的共享变量传递信息给另一个线程。

Object的 wait&notify 机制
Condition的await&signal 机制

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值