Java并发编程的艺术(一)-----并发编程的挑战及解决方案

来源:互联网 发布:如何提升淘宝店铺排名 编辑:程序博客网 时间:2024/05/29 04:40

简介

在进行Java多线程并发编程开发的时候,我们会遇到上下文切换、死锁以及硬件资源的相关问题,这些问题对程序执行的速度有着重要的影响。
ps:并发编程加快代码执行速度的原则是:将代码中串行化的部分变成并行执行。

上下文切换

是什么?

上下文切换就是程序在多处理器上面(也就是多个CPU)执行的时候,因为受限与于时间片,每个线程都有可能被突然暂停等待下次CPU的继续执行,暂定时肯定需要保存此时线程的执行状态以便重新执行,在这个线程被暂停保存到再次被加载执行的过程就是一次上下文切换。

多线程不一定快

正是由于上下文切换会带来资源的占用,并且线程得创建关闭这些也都需要开销,因此在一定程度上,多线程不一定比单线程运行得快。

如何减少上下文切换

既然我们要运用多线程进行并发编程,就必须得让程序并发执行得速度快起来,其中就需要减少上下文切换带来的资源占用以及开销,方法如下:

  • 无锁并发编程,因为多线程在竞争锁资源的时候,会引起上下文切换
  • 使用CAS算法,这样可避免使用锁,也就避免了上下文切换
  • 合理控制线程数
  • 协程:一个线程里面实现多任务的调度

死锁

是什么?

死锁指的是多个线程相互竞争同一个锁资源,而导致某个或多个线程一直处于等待状态使得该线程无法继续执行下去的情况。

示例:

import java.util.concurrent.locks.Lock;/** * Created by 罗浩 on 2017/9/22. */public class DeadLockDemo {    private Lock lockA;    private Lock lockB;    public static void main(String[] args) {        new DeadLockDemo().deadLock();    }    private void deadLock(){        Thread t1 = new Thread(new Runnable() {            @Override            public void run() {                synchronized (lockA){                    System.out.println("线程1竞争到了lockA");                    try {                        Thread.sleep(2000);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                    synchronized (lockB){                        System.out.println("线程1竞争到lockB" );                    }                }            }        });        Thread t2 = new Thread(new Runnable() {            @Override            public void run() {                synchronized (lockB){                    System.out.println("线程2拿到了lockB");                    synchronized (lockA){                        System.out.println("线程2拿到了lockA");                    }                }           }        });        t1.start();        t2.start();    }}

死锁分析

上面代码中,由于t1和t2两个线程在同时争取lockA和lockB的锁资源,最终将会导致t1和t2线程互相等待对方资源释放而程序一直无法情况,这便产生了死锁。

如何减少死锁

  • 避免一个线程同时使用多个锁
  • 避免一个线程在锁内同时占用多个资源
  • 尽量使用定时锁,在竞争锁超时能有相应的处理
  • 对数据库的加解锁必须在一个数据库连接里面
原创粉丝点击