学做土建资料员的网站,集图网,dw2020网页设计教程,网站空间买什么的好众所周知#xff0c;在Java的知识体系中#xff0c;并发编程是非常重要的一环#xff0c;也是面试的必问题#xff0c;一个好的Java程序员是必须对并发编程这块有所了解的。为了追求成为一个好的Java程序员#xff0c;我决定从今天开始死磕Java的并发编程#xff0c;尽量…众所周知在Java的知识体系中并发编程是非常重要的一环也是面试的必问题一个好的Java程序员是必须对并发编程这块有所了解的。为了追求成为一个好的Java程序员我决定从今天开始死磕Java的并发编程尽量弥补自己在这方面的知识缺陷。 并发必须知道的概念
在深入学习并发编程之前我们需要了解几个基本的概念。
同步和异步
同步和异步用请求返回调用的方式来理解相对简单。
同步可以理解为发出一个请求后必须等待返回结果才能执行下面的操作。
异步请求发出后不需要等待返回结果可以继续执行后续操作异步请求更像是在另一个 “空间” 中处理请求的结果这个过程不会影响请求方的其他操作。
举个生活中的例子比如我们去实体店买衣服挑选完款式后下单让售货员去仓库拿货在售货员拿货的过程你需要在店里等待直到售货员把衣服交给你后才算购物成功这就相当于同步的过程。
不过如果是在网上购物的话我们只需下单并完成支付对我们来说整个购物过程就算完成了。网上的商家接到订单会帮我们加紧安排送货这段时间我们可以去做其他的事比如去外面打个篮球之类的。等送货上门并签收商品就完事了这个过程就相当于异步。 并发和并行
并发和并行的功能很相似两者都可以表示多个任务一起执行的情况但本质上两者其实是有区别的。
严格意义上来说并行的多任务是真实的同时执行而并发更多的情况是任务之间交替执行系统不停的在多个任务间切换执行也就是 “串行” 执行。
最直接的例子的就是我们的计算机系统在单核CPU时代系统表面上能同时进行多任务处理比如听歌的同时又浏览网页但真实环境中这些任务不可能是真实并行的因为一个CPU一次只能执行一条指令这种情况就是并发系统看似能处理多任务是因为不停的切换任务但因为时间非常短所以在我们的感官来说就是同时进行的。而计算机系统真实的并行是随着多核CPU的出现才有的。
临界区
临界区表示公共资源或是共享数据可以被多个线程使用。但是每次只能有一个线程使用它一旦临界区的资源被占用其他线程就必须等到资源释放后才能继续使用该资源。在Java程序开发中对于这样的资源一般都需要做同步的操作例如下面的这段代码用的就是synchronized关键字来对临界区资源进行同步
public class SyncTest implements Runnable {
//临界区资源
public static SyncTest instance new SyncTest();
Override
public void run() {
synchronized (instance) {
}
}
public static void main(String[] args) throws InterruptedException {
Thread t1 new Thread(new SyncTest());
Thread t2 new Thread(new SyncTest());
t1.start();
t2.start();
t1.join();
t2.join();
}
}
阻塞和非阻塞
阻塞和非阻塞通常用来形容多线程间的相互影响。比如一个线程占用了临界区的资源那么其他需要这个资源的线程就必须等待。等待的过程会使线程挂起也就是阻塞。如果临界区的资源一直不释放的话那么其他阻塞的线程就都不能工作了。 非阻塞则相反强调的是线程之间并不互相妨碍所有的线程都会不断尝试向前执行。
死锁、饥饿和活锁
这三种情况表示的是多线程间的活跃状态对于线程来说以上的情况都是 “非友好” 的状态。
1、死锁一般是指两个或者两个以上的线程互相持有对方所需的资源并且永远在等待对方释放的一种阻塞状态。例如有两个线程A和B同时共享临界区的资源C当A占用C时B处于阻塞状态然而A的释放需要用到B的资源这样一来就变成了A一直在等待BB也一直在等待A互相之间永远在等待对方释放的状态。
一般来说死锁的发生是由于程序的设计不合理导致而且死锁很难解决最好的方式就是预防。
2、饥饿是指某一个或者多个线程因为种种原因无法获得所需的资源导致一直无法执行。比如它的线程优先级太低而高优先级的线程不断抢占它所需的资源导致低优先级资源无法工作。
3、活锁的情况是线程一种非常有趣的情况在生活中我们可能会碰到这样的情况那就是出门的时候可能会遇到有人要进门你打算让他先进门他又打算让你先出门结果两个人都互相退后了然后你打算先出门时对方也向前一步来来回回就一直卡在门口。当然这种事情正常人很快就能解决但如果是线程碰到就没那么幸运了。
如果两个线程占用着公共的资源并且秉承着 “谦让” 的原则主动把资源让给他人使用你让我也让这样就造成资源在两个线程间不断跳动但线程之间都拿不到资源的情况这样的情况就是活锁了。 线程安全
线程安全指的是多线程的安全。如果一段程序可以保证被多线程访问后仍能保持正确性那么程序就是线程安全的。一般来说线程安全注重的是多线程开发中的共享数据的安全。就比如下面这段代码
public class ThreadSafety implements Runnable{
//共享数据
public static int i 0;
public void increase(){
for (int j 0;j10; j){
i;
}
}
Override
public void run() {
increase();
}
public static void main(String[] args) throws Exception{
ThreadSafety demo new ThreadSafety();
Thread t1 new Thread();
Thread t2 new Thread();
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(i);
}
}
两个线程 t1 和 t2 同时开启执行run方法在我们的预想中如果是线程安全的话那么main的执行结果应该是20但是因为 i 是共享数据而程序没有对 i 的操作做同步的处理最终运行的结果并不是20所以这种情况就不是线程安全的情况。
解决的办法也比较简单可以利用synchronized关键字来修饰方法或代码块这部分的知识也是并发编程中非常重要的一块之后单独写篇文章出来细说。
为了让学习变得轻松、高效今天给大家免费分享一套Java入门教学资源。帮助大家在成为Java架构师的道路上披荆斩棘。需要入门的资料欢迎加入学习交流群928505736