Chapter 1-- 并发编程的挑战

并发编程的挑战

引入

并发编程的目的是为了让程序运行得更快,但是进行并发编程会面临以下几种挑战:

  • 上下文切换
  • 死锁
  • 软硬件资源限制

1. 上下文切换

- 什么是上下文切换?

时间片轮转 -- 任务状态 -- 保存再加载 -- 上下文切换

cpu通过时间片分配算法来循环执行任务,任务A执行一个时间片后会切换到任务B;在切换前会保存任务A的状态,为的是:在下回切回任务A时能够再次加载任务A的状态。

【总结】任务从保存到再加载的过程就是一次上下文切换,上下文切换会影响多线程的执行速度


- 串行、并行、并发?


- 并发执行一定快于串行执行吗?

答:不一定

并发执行慢于串行的原因是:线程有创建和上下文切换的开销


- 如何减少上下文切换?

  • 无锁并发编程:多线程处理数据时,避免使用锁

  • CAS算法:使用CAS算法更新数据,不需要加锁

  • 使用最少线程:避免创建不必要线程

  • 协程:单线程内维持多个任务的切换


2. 死锁

- 什么是死锁?

死锁:因进程之间相互竞争资源导致相互等待而无法推进的情况


- 实现一个死锁?

public class DeadLockDemo {

    private static String A = "A";
    private static String B = "B";

    public static void main(String[] args){
        new DeadLockDemo().deadLock();
    }

    private void deadLock(){
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (A){
                    try{
                        Thread.currentThread().sleep(2000);
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }

                    synchronized (B){
                        System.out.println("1");
                    }
                }
            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (B){
                    synchronized (A){
                        System.out.println("2");
                    }
                }
            }
        });

        t1.start();
        t2.start();
    }
}


- 怎么避免死锁?

  • 避免一个线程同时获取多个锁

  • 避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源

  • 尝试使用定时锁替代使用内部锁机制

  • 数据库锁的加锁和解锁必须在一个数据库连接里


3. 资源限制的挑战

- 什么是资源限制?

并发编程时,程序执行速度受限于资源

(资源包括软件资源和计算机硬件资源)


- 资源限制带来的问题?

并发编程中加快代码执行速度的原则是:串行-->并发;但若受限于资源,想要并发执行的代码仍然以串行方式执行,这时,代码执行速度不快反慢(增加了上下文切换和资源调度时间)


- 如何解决资源限制的问题?

  • 硬件资源限制:使用集群并行执行程序

  • 软件资源限制:使用资源池复用资源


- 如何在资源限制情况下并发编程

根据不同资源限制调整程序的并发度


参考书目

《Java并发编程的艺术》

posted @ 2022-07-13 22:22  Claire_2099  阅读(13)  评论(0编辑  收藏  举报