目录
串行,并行与并发:
并发编程的目的
如何保证多线程的安全(并发编程思想)
写后读思想:(一个线程写后再让另一个线程读)
如何保障写后读?
1、加锁:(synchronized)
2、CAS 比较并交换
今天,我们从最基本的角度来谈谈并发编程,本篇文章主要来聊聊并发编程的整体思路,具体的知识和原来我们放在之后的文章。
首先补充一个小概念:
串行,并行与并发:
串行:n个任务 挨个执行
并行:多个任务 同一时刻发生 (多个程序可同时运行 多个任务分配到多个处理器上)
并发:多个任务 同一时间段发生 (每一时刻只能有一个程序执行,但由于CPU高速运转,使多个任务快速切换,程序交替运行)
并发编程的目的
并发编程的目的是为了让程序运行得更快,但是,并不是启动更多的线程就能让程序最大限度地并发执行。在进行并发编程时,如果希望通过多线程执行任务让程序运行得更快,会面临非常多的挑战,比如上下文切换的问题、死锁的问题,以及受限于硬件和软件的资源限制问题。
所以呢,我们不是一上来就要开多线程的,只有在CPU产生计算浪费且浪费比例较大的情况下,才使用多线程。而多线程开多少个线程合适?这与CPU浪费比例以及上下文开销有关,能让CPU刚好打满合适。
聊完了多线程的使用场景,我们再来聊聊,并发编程的思想:
如何保证多线程的安全(并发编程思想)
写后读思想:(一个线程写后再让另一个线程读)
一个线程读取到其他线程写之后的内容,基于其他线程的计算结果,然后再去操作,才能计算准确
如何保障写后读?
1、加锁:(synchronized)
先加锁再操作(这样一个线程对其加锁了,其他线程就不能再对其读取操作,当(写)操作完之后(数据已经更新回来)再释放锁,此时其他线程竞争式加锁,竞争加锁成功的 再进行读取操作
代码举例:
普通方法加synchronized锁,则线程想调用时必须先对其加锁,此时其他线程不能重复加锁亦不能调用,直到该线程执行完(完成写回操作)此方法释放锁之后,其他线程才能加锁调用(保证写后读思想)
类锁:(静态加锁方法)
类锁解释:当某线程调用一个静态加锁方法后,触发类锁,锁住了整个静态方法区,此时任何一个加锁的静态方法都不可被其他线程调用
如下代码:
假设t1线程调用getA()方法,触发类锁,锁住方法区。然后执行完getA()方法,释放类锁,此时t1线程时间片到期,t2线程开始执行,调用getA()方法,读到a数据,但此时t1线程还没完成写操作。没有做到“写后读”,此过程不安全。
2、CAS 比较并交换
线程每次读写操作时,都会将附加变量+1,这样其他线程读取时会先与这个附加变量对比,如果不一致,则不可读取进行操作,如果一致再进行写操作(也是写后读思想)