游乐游手机版
首页/AI教程/文章详情

软件开发进阶技能:编程语言深度运用(三)

时间:2026-06-07 16:10
并发与异步编程模型利用多核提升性能,涉及线程与协程、异步模型从回调到async await的演进。多线程同步需用锁、原子操作或并发集合处理数据竞争,避免死锁需固定锁顺序或使用高级同步工具。

第三部分:并发与异步编程模型 —— 驾驭多核时代的力量

多核处理器已经成为现代计算机的标配,如何充分借助并发与并行来提升程序性能,成为开发者必须掌握的核心技能。但并发编程有一个显著特点:它既能带来性能提升,也可能引发诸多难题——数据竞争、死锁、线程安全,每一个都不容小觑。因此,深入理解一门语言的并发模型,才是安全高效编写并发程序的关键。

3.1 并发的基本概念:并行 vs 并发,线程 vs 协程

先来厘清并发与并行的区别。并发,是指多个任务在逻辑上“同时”进行,实际上是通过时间片轮转交替切换;并行,则是多个任务在物理上真正同时执行,这需要多核处理器的支持。打个比方:一个人轮流吃三碗饭是并发,三个人各自同时吃一碗才是并行。

那么线程和协程又有何不同?线程是操作系统调度的最小单位,切换成本大约在几微秒到几十微秒之间。而协程是由语言运行时在用户态调度的轻量级“线程”,切换成本低至纳秒级,创建几十万个协程也毫无压力。

image.png

3.2 异步编程模型:回调 → Promise → async/await 的演进

异步编程的核心在于:程序在等待I/O操作时,可以腾出手来处理其他任务,避免线程白白阻塞。掌握异步模型,是编写高响应、高吞吐应用的前提条件。

来看一个实际例子:JavaScript的Promise链和async/await。

// 模拟异步操作
function fetchUser(id) {
    return new Promise(resolve => {
        setTimeout(() => resolve({ id, name: `User${id}` }), 100);
    });
}

function fetchPosts(userId) {
    return new Promise(resolve => {
        setTimeout(() => resolve([`Post1 by ${userId}`, `Post2 by ${userId}`]), 100);
    });
}

// Promise链式调用
fetchUser(1)
    .then(user => {
        console.log(user.name);
        return fetchPosts(user.id);
    })
    .then(posts => {
        console.log(posts);
    })
    .catch(err => console.error(err));

// async/await 更清晰的写法
async function displayUserContent(id) {
    try {
        const user = await fetchUser(id);
        console.log(user.name);
        const posts = await fetchPosts(user.id);
        console.log(posts);
    } catch (err) {
        console.error(err);
    }
}

displayUserContent(2);

这里的关键在于:async函数始终返回一个Promise,await会在当前函数内部暂停执行,直到Promise完成——但注意,它并不会阻塞事件循环。相比曾经的“回调地狱”(Callback Hell),这种写法读起来要友好得多。

再看看Python的asyncio如何实现并发网络请求。

import asyncio
import aiohttp

async def fetch_url(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    urls = [
        'https://example.com',
        'https://example.org',
        'https://example.net',
    ]
    async with aiohttp.ClientSession() as session:
        tasks = [fetch_url(session, url) for url in urls]
        results = await asyncio.gather(*tasks)
        for url, html in zip(urls, results):
            print(f"{url}: {len(html)} bytes")

asyncio.run(main())

这里asyncio.gather并发地调度多个协程。当程序等待网络响应时,事件循环可以切换到其他协程继续执行,从而在I/O密集型场景下实现高效并发。这,才是异步编程的真正价值所在。

3.3 多线程同步:锁、原子操作、并发集合

一旦多个线程共享可变状态,同步机制就必须上场了。否则数据一致性将无从谈起。

以Java的线程安全计数器为例,我们看看不同实现方式的性能差异。

// 非线程安全
class UnsafeCounter {
    private int count = 0;
    public void increment() { count++; }  // 多线程下丢失更新
    public int get() { return count; }
}

// 使用synchronized
class SynchronizedCounter {
    private int count = 0;
    public synchronized void increment() { count++; }
    public synchronized int get() { return count; }
}

// 使用AtomicInteger(无锁CAS)
import java.util.concurrent.atomic.AtomicInteger;
class AtomicCounter {
    private AtomicInteger count = new AtomicInteger(0);
    public void increment() { count.incrementAndGet(); }
    public int get() { return count.get(); }
}

// 使用LongAdder(高并发下更好)
import java.util.concurrent.atomic.LongAdder;
class AdderCounter {
    private LongAdder count = new LongAdder();
    public void increment() { count.increment(); }
    public long get() { return count.sum(); }
}

性能方面:synchronized在低竞争场景下已经够用;AtomicInteger基于CAS,没有锁的开销,但高竞争时可能频繁自旋;而LongAdder则通过分段计数进一步降低竞争。进阶开发者会根据场景灵活选择最合适的方案。

再看Go语言中的Mutex和RWMutex。

type SafeCounter struct {
    mu sync.Mutex
    m  map[string]int
}

func (c *SafeCounter) Inc(key string) {
    c.mu.Lock()
    defer c.mu.Unlock()
    c.m[key]++
}

func (c *SafeCounter) Value(key string) int {
    c.mu.Lock()
    defer c.mu.Unlock()
    return c.m[key]
}

// 读多写少场景使用RWMutex,允许并发读
type SafeMap struct {
    mu sync.RWMutex
    m  map[string]string
}

func (s *SafeMap) Get(key string) string {
    s.mu.RLock()
    defer s.mu.RUnlock()
    return s.m[key]
}

处理读多写少的场景时,RWMutex更为合适——它允许多个读操作并发执行,写操作则独占访问。

3.4 数据竞争与死锁的检测与避免

数据竞争的本质是:多个线程同时访问同一内存位置,且至少有一个是写操作,同时没有任何同步保护。Go语言内置了数据竞争检测器,只需在测试时加上 go test -race 就能直接定位问题。

而死锁,则是指两个或多个线程互相等待对方持有的锁,最终导致所有线程都无法继续执行。

来看一个经典的Java死锁示例。

public class DeadlockDemo {
    private final Object lock1 = new Object();
    private final Object lock2 = new Object();

    public void method1() {
        synchronized(lock1) {
            sleep(100);  // 模拟工作
            synchronized(lock2) {
                System.out.println("method1 done");
            }
        }
    }

    public void method2() {
        synchronized(lock2) {
            sleep(100);
            synchronized(lock1) {
                System.out.println("method2 done");
            }
        }
    }

    private void sleep(int ms) { try { Thread.sleep(ms); } catch(Exception e) {} }

    public static void main(String[] args) {
        DeadlockDemo demo = new DeadlockDemo();
        new Thread(demo::method1).start();
        new Thread(demo::method2).start();
    }
}

要避免死锁,以下几个原则值得牢记:

  • 固定锁顺序:始终以相同的顺序获取锁。比如先拿lock1再拿lock2
  • 使用超时尝试:Java中的tryLock(timeout),获取失败时释放已持有的锁,然后重试。
  • 减小锁粒度:采用并发集合(如ConcurrentHashMap)或无锁数据结构来替代粗粒度锁。
  • 使用更高级的同步工具:像java.util.concurrent包中的SemaphoreCountDownLatch等,比手动管理锁更加安全可靠。
来源:https://developer.aliyun.com/article/1739332
上一篇阿里云通用算力型u2i实例2核4G与4核8G性能价格解析 下一篇软件开发进阶技能:编程语言深度运用第五篇
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
幻灯片排版优化AI智能助手,节省时间与精力
AI教程 · 2026-07-01

幻灯片排版优化AI智能助手,节省时间与精力

说起来,今天想和大家聊聊一个特别实在的话题:怎么用AI工具把PPT排版效率提上去,真正省下时间和精力。谁不想在忙忙碌碌的工作里找到点儿省事的诀窍呢?我有个朋友,为了准备一次重要汇报,连着熬了三个晚上折腾PPT,最后出来的效果也就是勉强及格。要是当时他能用上AI工具,结果会不会完全不一样?PPT排版优

AI排版软件让文档制作轻松又高效
AI教程 · 2026-07-01

AI排版软件让文档制作轻松又高效

AI智能排版工具通过自动识别文档结构、调整格式,显著提升排版效率。实际案例显示,文档处理时间可缩短约50%,项目交付效率提高40%。其功能涵盖自动排版、模板库、智能校对等,重构了文档制作流程,使用户专注内容创作,提升专业形象与市场竞争力。

Karpathy晒邮件曝光注意力机制真正起源:10年前三项独立研究
AI教程 · 2026-07-01

Karpathy晒邮件曝光注意力机制真正起源:10年前三项独立研究

2014年,三项研究几乎同时独立提出注意力机制:DzmitryBahdanau在YoshuaBengio实验室开发出RNNSearch(后称注意力),AlexGraves和JasonWeston团队也发表了类似机制。该思想源于解决循环神经网络信息瓶颈的需求,采用可微加权平均,成为深度学习核心算法。

如何选择AI排版工具与技巧提升内容创作效率
AI教程 · 2026-07-01

如何选择AI排版工具与技巧提升内容创作效率

AI排版工具推荐与技巧:如何提升内容创作效率与视觉设计效果其实,AI排版早已成为内容创作领域的热门话题。在信息爆炸的时代,大家都想知道如何让内容在海量信息中脱颖而出。简单来说,AI排版就是借助人工智能技术自动化处理文本、图像等内容的布局与设计。不妨想象一下:星巴克菜单上那些赏心悦目的排版,背后可能就

AI公文写作助手助力文档创作,高效节省时间精力
AI教程 · 2026-07-01

AI公文写作助手助力文档创作,高效节省时间精力

AI公文写作助手可将企业文档处理效率提升30%以上,北京国企公文撰写时间缩短50%。WPSAI文档处理能一键生成专业文档,深圳创业公司效率提高70%。未来AI将更智能化,自动调整文档风格。