并发编程—《Java并发编程的艺术》学习笔记 第一章 并发编程的挑战

Java并发编程的艺术
所有笔记:https://www.jianshu.com/nb/33534473
Github地址:https://github.com/ilssio/java-concurrency-programming-ilss

1.1上下文切换

​ 多线程的支持:CPU通过给每个线程分配CPU时间片来实现这个机制。

​ 上下文切换:CPU通过分配时间片算法循环执行任务时,任务切换前会保存前一个任务的状态,以便切回任务,任务从保存到再次加载的过程就是一次上下文切换。上下文切换会影响多线程的执行速度。

1.1.1多线程一定快吗?

  • 代码见part01中ConcurrencyTest类。

    package io.ilss.concurrency.part01;
    
    /**
     * className ConcurrencyTest
     * description ConcurrencyTest
     *
     * @author feng
     * @version 1.0
     * @date 2019-01-21 12:47
     */
    public class ConcurrencyTest {
        private static final long count = 100001L;
    
        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() {
                    long a = 0;
                    for (long i = 0; i < count; i++) {
                        a += 5L;
                    }
                }
            });
            thread.start();
            long b = 0;
            for (long i = 0; i < count; i++) {
                b--;
            }
            thread.join();
            long time = System.currentTimeMillis() - start;
            System.out.println("Concurrency : " + time + "ms, b = " + b);
        }
    
        private static void serial() {
            long start = System.currentTimeMillis();
            long a = 0;
            for (long i = 0; i < count; i++) {
                a += 5;
            }
            long 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);
        }
    }
    

通过更改count从1万到1亿可看成,执行count越低,串行执行效率更高。这是因为线程有创建和上下文切换的开销。但是到了一定的数量过后,多线程的优势就会体现出来。

1.1.2

  • 可以用Lmbench3测量上下文切换的时间 (Lmbench3是一个性能分析工具)

1.1.3 如何减少上下文切换

​ 减少上下文切换的方法:无锁并发编程、CAS算法、使用最少线程、使用协程

  • 无锁并发编程:即用一些方法来避免使用锁。
  • CAS算法:Atomic包使用CAS算法更新数据
  • 只用最少线程:避免创建不需要的线程
  • 协程:在单线程中实现多任务调度,并在单线程中维持多个任务间的切换

1.1.4 减少上下文切换实战

减少WAITING线程,系统上下文切换的次数就会少。线程从WAITING到RUNNABLE都会进行一次上下文切换。

1.2 死锁

代码见part01中的DeadLockDemo类

package io.ilss.concurrency.part01;

/**
 * className DeadLockDemo
 * description DeadLockDemo
 *
 * @author feng
 * @version 1.0
 * @date 2019-01-21 16:28
 */
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(() -> {
            synchronized (A) {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (B) {
                    System.out.println("1");
                }
            }
        });
        Thread t2 = new Thread(() ->{
            synchronized (B) {
                synchronized (A) {
                    System.out.println("2");
                }
            }
        });
        t1.start();
        t2.start();

    }
}
  • t1(Thread-0)拿到A锁过后sleep2s,t2("Thread-1)同时进入B锁代码块,由于t1还在执行A锁的代码块阻塞进程,等t1线程2s时间到了想进入B的代码块时,由于t2还在执行B锁的代码块,就行形成了拿了A的t1要B,拿了B的t2要A,形成死锁。如下信息所示
Java stack information for the threads listed above:
===================================================
"Thread-1":
    at io.ilss.concurrency.part01.DeadLockDemo.lambda$deadLock$1(DeadLockDemo.java:36)
    - waiting to lock <0x000000076ac26378> (a java.lang.String)
    - locked <0x000000076ac263a8> (a java.lang.String)
    at io.ilss.concurrency.part01.DeadLockDemo$$Lambda$2/2129789493.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:748)
"Thread-0":
    at io.ilss.concurrency.part01.DeadLockDemo.lambda$deadLock$0(DeadLockDemo.java:29)
    - waiting to lock <0x000000076ac263a8> (a java.lang.String)
    - locked <0x000000076ac26378> (a java.lang.String)
    at io.ilss.concurrency.part01.DeadLockDemo$$Lambda$1/1607521710.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:748)

Found 1 deadlock.

注:先使用jps找到运行所在的pid,然后用jstack <pid> 查看如上信息

避免死锁的几个常见的方法:

  • 避免一个线程同时获取多个锁
  • 避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源
  • 尝试使用定时锁,使用lock.tryLock(timeout)来替代内部锁机制
  • 对于数据库锁,枷锁和解锁必须在一个数据库连接里,否则会出现解锁失败的情况。

1.3 资源限制的挑战

  • 并发编程时需要考虑:硬件资源如带宽的上传/下载速度、硬盘的读写速度和CPU的处理速度。软件资源如数据库连接数、socket连接数等
  • 资源限制引发的问题:多线程程序由于资源限制,仍然串行执行,会因为上下文切换和资源调度而降低效率
  • 解决资源限制的问题:硬件上可以使用集群,不同的机器处理不同的数据;软件上可以考虑使用资源池将资源复用,如:数据库连接池、socket连接复用、调用webservice接口获取数据时,只建立一个连接。
  • 在资源限制情况下进行并发线程:根据不同的资源限制调整程序的并发度。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容