《并发编程的艺术》第一章 并发编程的挑战

1.1 上下文切 

CPU 过时间 片分配算法来循 环执 行任 ,当前任 务执 行一个 时间 片后会切 到下一个 任务 。但是,在切 前会保存上一个任 的状 ,以便下次切 个任 务时 ,可以再加 载这 个任务 的状 。所以任 从保存到再加 程就是一次上下文切

1.1.1 线程一定快

public class Test01 {
    private static final long count = 10000l;

    public static void main(String[] args) throws InterruptedException {
        concurrency();
        serial();
    }
    //多线程执行
    private static void concurrency() throws InterruptedException {
        long start = System.currentTimeMillis();
        Thread thread = new Thread(new Runnable() {
            public void run() {
                int a = 0;
                for (long i = 0; i < count; i++) {
                    a += 5;
                }
            }
        });
        thread.start();
        int b = 0;
        for (long i = 0; i < count; i++) {
            b--;
        }
        long time = System.currentTimeMillis() - start;
        //join() 的作用:让“主线程”等待“子线程”结束之后才能继续运行。
        thread.join();
        System.out.println("concurrency :" + time + "ms,b=" + b);
    }
    //穿行执行
    private static void serial() {
        long start = System.currentTimeMillis();
        int a = 0;
        for (long i = 0; i < count; i++) {
            a += 5;
        }
        int b = 0;
        for (long i = 0; i < count; i++) {
            b--;
        }
        long time = System.currentTimeMillis() - start;
        System.out.println("serial:" + time + "ms,b=" + b + ",a=" + a);
    }
}

1.1.2 测试上下文切次数和时长 

· 使用 Lmbench3 [1] 可以 量上下文切 时长
· 使用 vmstat 可以 量上下文切 的次数。

 1.1.3 如何减少上下文切

减少上下文切 的方法有无 发编 程、 CAS 算法、使用最少 线 程和使用 程。
 
· 发编 程。多 线 锁时 ,会引起上下文切 ,所以多 线 理数据 ,可以用一 些办 法来避免使用 ,如将数据的 ID 按照 Hash 算法取模分段,不同的 线 理不同段的数据。
 
·CAS 算法。 Java Atomic 包使用 CAS 算法来更新数据,而不需要加
 
· 使用最少 线 程。避免 建不需要的 线 程,比如任 很少,但是 建了很多 线 程来 理, 这 样会造成大量 线 程都 于等待状
 
· 程:在 单线 程里 实现 多任 度,并在 单线 程里 持多个任 务间 的切

1.1.4 减少上下文切换实战

1.2

段代会引起死,使线t1线t2互相等待

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() {
            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() {
            public void run() {
                synchronized (B) {
                    synchronized (A) {
                        System.out.println("2");
                    }
                }
            }
        });
        t1.start();
        t2.start();
    }
}
段代 只是演示死 景,在 现实 中你可能不会写出 这样 的代 。但是,在一些更 为 复杂 景中,你可能会遇到 这样 问题 ,比如 t1拿到锁之后,因为一些异常情况没有释放锁 (死循环)。又或者是t1拿到一个数据库锁,释放锁的时候抛出了异常,没释放掉。
一旦出 业务 是可感知的,因 不能 继续 提供服 了,那么只能通 dump 线 看到底是哪个线 程出 问题
在我 避免死 的几个常 方法。
 
· 避免一个 线 程同 时获 取多个
 
· 避免一个 线 程在 内同 占用多个 源,尽量保 每个 只占用一个 源。
 
· 尝试 使用定 时锁 ,使用 lock.tryLock timeout )来替代使用内部 机制。
 
· 于数据 库锁 ,加 和解 在一个数据 库连 接里,否 会出 的情况。

1.3 源限制的挑

(1)什么是源限制

源限制是指在 行并 发编 ,程序的 行速度受限于 算机硬件 源或 资源。例如,服务器的带宽只有2Mb/s,某个资源的下载速度是1Mb/s每秒,系统启动10个线程下载资源,下载速度不会变成10Mb/s,所以在进行并发编程时,要考虑这些资源的限制。硬件资源限制有带宽的上传/下载速度、硬盘读写速度和CPU的处理速度。软件资源限制有数据库的连接数和socket连接数等
 
2 源限制引 问题
在并 发编 程中,将代 码执 行速度加快的原 是将代 中串行 行的部分 成并 发执 行, 但是如果将某段串行的代码并发执行,因为受限于资源,仍然在串行执行,这时候程序不仅不会加快执行,反而会更慢,因为增加了上下文切换和资源调度的时间。
 
3 )如何解决 源限制的 问题
对于硬件资源限制,可以考虑使用集群并行执行程序 。既然 机的 源有限制,那么就 让程序在多机上运行。比如使用ODPS Hadoop 或者自己搭建服 器集群,不同的机器 理不同的数据。可以通过 数据 ID% 机器数 算得到一个机器 号,然后由 对应编 号的机器 这笔数据。 对于软件资源限制,可以考虑使用资源池将资源复用 。比如使用 接池将数据 Socket连接复用,或者在 webservice 接口 取数据 ,只建立一个 接。
 
4 )在 源限制情况下 行并 发编 如何在 源限制的情况下, 程序 行得更快呢?方法就是, 根据不同的资源限制调整程序的并发度 ,比如下 文件程序依 于两个 —— 带宽 和硬 盘读 写速度。有数据 操作 时,涉及数据 库连 接数,如果 SQL 行非常快,而 线 程的数量比数据 库连 接数大很多, 则某些线 程会被阻塞,等待数据 库连 接。

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值