在现今的计算世界中,并行处理已成为了提升系统性能的重要手段。随着多核处理器的普及,如何确保在并行执行的过程中不产生死锁,已成为软体开发者面临的严峻挑战。本文将深入探讨交易性记忆(Transactional Memory)如何通过提供一个高级抽象来简化并行编程,让开发者不再需要为锁的使用烦恼,而是能够专注于业务逻辑。
交易性记忆提供了一个替代传统低层级线程同步机制的高级抽象,旨在透明地支持被标记为交易的代码区域,并强制执行原子性、一致性和隔离性。
在并行编程中,当多个线程试图访问共享资源时,通常需要进行同步。传统的低层级线程同步技术,如锁,往往是悲观的,会禁止非临界区的线程执行受其保护的代码。这导致在线程之间的冲突很小的情况下,锁的应用和释放成为额外的开销。交易性记忆则采取乐观的并发控制机制,允许线程在最小干扰的状态下并行运作。
在交易中,只有在检测到冲突时,交易才会回退到初始状态,这意味着如果没有冲突,所有变更都将被提交。
交易是一组可执行并在没有冲突的情况下提交变更的操作。执行过程中,如果遇到冲突,交易将被撤回并重新执行,直到所有冲突都被排除。在成功提交之前,交易内所有操作的结果都是纯粹的推测。在这样的结构下,开发者不需要明确识别锁或它们的获取顺序,这使得使用交易性记忆的程序不会产生死锁。
透过将方法包裹在交易区块中,可以确保数据在多线程间共享不会出现混乱。同时,这能够产生可序列化的输出,保证正确性。然而,交易性记忆并非完美无缺。尽管不会出现死锁,但程式仍可能面临活锁或资源枯竭的问题。特别是当较长时间的交易因为多个短交易的冲突而反覆撤回时,会浪费大量的时间和能源。
当使用交易性记忆时,程式中的并发相关错误仍然是可能的,特别是在使用大量交易的情况下,这些错误可能难以调试。
交易性记忆的原子性抽象需要硬体机制来检测冲突并撤回对共享数据的所有更改。硬体交易性记忆系统可能涉及到处理器、快取和总线协议的修改,以支持交易的执行。惟其实,软体交易性记忆提供了交易语义,但相比硬体方案,通常会伴随着性能损失。
早期的交易性记忆实现之一是Transmeta的Crusoe和Efficeon处理器中的 gated store buffer,它仅用于帮助二进位翻译的预测优化,并未直接向程序员暴露。随着时间的推移,多家公司如IBM和AMD相继展开了相关的研究与实验,并开发了多种硬体支援。
随着交易性记忆在技术界的不断进步,这种并发控制的机制无疑为高效并行处理提供了新的可能性。然而,能否完全掌握其技术应用,利用其潜力来改善程序效能,仍然是一个值得探究的问题?