并发编程笔记(一):并发编程的挑战和解决方案

并发系列的文章都是根据阅读《Java 并发编程的艺术》这本书总结而来,想更深入学习的同学可以自行购买此书进行学习。

并发编程的目的是为了让程序运行的更快,但是启动更多的线程不一定会让程序能够最大程度的并发执行,甚至有时候,并发比串行还要慢。在使用并发编程的时候,会面临许多挑战。

上下文切换

单核处理器也是可以支持多线程执行代码的。CPU通过分配时间片来实现这个机制。时间片是 CPU 分配给各个线程的时间,因为时间片很短,所以 CPU 会通过不断切换线程执行,让我们感觉多个线程是同时执行的。

每次时间片切换之前都会保存上一个任务的状态,用来方便下次切换回这个任务的时候,可以再次加载这个任务的状态。这个保存到加载的过程就是一次上下文切换。

这样的切换是会影响多线程的执行效率的。想象我们看一本英文书籍,如果遇到单词不认识,我们会去查阅词典,但是在查阅之前,我们得先记住我们看到那一页了,以便等到查到单词后还能继续在之前看的位置读下去。虽然这样能够保证阅读的连贯性,但阅读的速度必然是受到影响的。

多线程并发执行不一定比串行执行快。测试发现,串行和并行做同一件循环操作,在一定达到循环次数之前,并发是没有串行速度快的。这正是因为线程的创建以及上下文切换有开销的缘故。

通过一些工具我们可以度量上下文带来的消耗:

  • 使用 Lmbench3 可以测量上下文切换的时长
  • 使用 vmstat 可以测量上下文切换的次数

那么如何减少上下文的切换呢?

  • 无锁并发编程。多线程竞争锁时,会引起上下文切换,所以可以用一线方法来避免使用锁。例如将数据的 ID 按 Hash 算法取模分段,不同的线程处理不同段的数据。
  • CAS 算法。Java 的 Atomic 包使用 CAS 算法来更新数据,不需要加锁
  • 使用最少线程:避免创建不必要的线程,如果创建了很多多余的线程,将会造成大量的线程处于等待状态。
  • 协程:在单线程里实现多任务的调度,并在单线程里维持多个任务间切换。

死锁

锁是个非常有用的工具,使用也很简单易懂,但可能会引起死锁,从而导致系统不可用。在一些复杂的场景中,可能会遇到死锁问题,比如线程 t1 拿到锁之后,因为一些异常情况没有释放锁(例如死循环)。又或者是 t1 拿到了一个数据库锁,释放锁的时候抛出了异常,没有释放掉。

一旦出现死锁,业务是可以感知的,因为无法继续提供服务了,我们可以通过 dump 现场来查看哪个线程除了问题,并根据日志信息进行跟踪代码。

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

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

资源限制的挑战

资源限制可以分为计算机硬件资源软件资源

硬件资源限制有宽带速度、硬盘读写速度和 CPU 处理速度。如果宽带速度只有 2Mb/s,某个资源下载速度是 1Mb/s,但系统即使启动了 10 个线程下载资源,下载速度也不会编程 10Mb/s。

软件资源限制有数据库的连接数和 socket 连接等。

因为资源限制的原因,会导致有时候并发执行的任务因为资源不足,甚至还没有串行执行速度快。比如因为开了多线程导致了一些资源的请求,但资源又不够用,就会导致一些资源调度和上下文切换的开销。

对于硬件资源限制,可以使用集群并行执行程序。对于软件资源,可以考虑使用资源池将资源复用。在资源限制的情况下,要根据不同的资源限制调整程序的并发度。例如有数据库操作时,设计数据库连接数,如果 SQL 语句执行的非常快,但线程的数量要比数据库连接数大很多,那么某些线程将会被阻塞,等待数据库连接。

总结

并发编程有很多挑战,如果并发程序写的不严谨,出现了问题,定位和解决起来都比较棘手和耗时。所以对于 Java 开发工程师而言,建议多使用 JDK 并发包提供的并发容器和工具类来解决并发问题,这些类已经通过了充分的测试和优化,以上问题都是可以解决的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容