Scala语言有很多优点,比如简洁、强大的表现力等等。但我最关注的,是它在并发编程方面的优势。
Scala通过强调对象的不变性
以及使用基于事件的模型进行线程间通信
使得实现并发应用变得简单。
不变对象
并发编程之所以这么困难,很大一个原因在于对象的可变性。要在充斥着大量可变对象的程序里面实现安全并发,需要非常繁琐以及复杂易错的同步操作来保证状态更新的同步。
比如下面这段代码(java的例子),可能你会认为它已经是线程安全的了,因为所有的方法都已经被同步。
class Account {
private int balance;
synchronized public int getBalance() {
return balance;
}
synchronized public void incrementBalance() {
balance++;
}
}
但是问题来了,当顺序调用这两个方法的时候,比如:
account.incrementBalance();
account.getBalance();
这时并不是线程安全的,在第一个方法调用结束之后,可能会被其它线程获取对象的锁,修改account的balance。
在命令式编程语言里面,命令查询分离是一个普遍使用的原则。意即:一个方法要么进行一次命令(执行一个操作,通常会修改状态),要么进行一次查询(返回一些状态, 但并不修改状态),而不应该同时执行命令以及查询。从面向对象的角度看,这是一个良好的设计;但从并发编程的角度看,它却带来了一些问题,使得并发编程实现更加困难。上面就是一个很好的例子。
要使得上面这段代码变得线程安全,可以通过破坏命令查询分离原则来实现:
synchronized public int incrementAndGetBalance() {
balance++;
return balance;
}
从上面的例子看到,在可变对象的环境中实现并发编程是困难的。而不变对象,意即线程安全的对象,使得我们不必担心共享对象会被多个线程同时修改而无法保持它的正确性:因为它本身就不可修改。我们可以把不变对象很放心地扔到多线程环境中,任意使用。
问题又来了,如果要“修改状态”怎么办?很简单,创建一个新的对象。还是上面那个例子,我们把它修改成一个Scala的不变对象类。并在伴生对象里面实现increment方法,此方法会返回一个新的account对象,balance值为原有对象的值加1所得。
class Account (val balance: Integer) {
def getBalance() = balance
}
object Account {
def increment(account: Account): Account {
new Account(account.getBalance() + 1)
}
}
通过强调不变对象的使用,并发编程变得简单了很多。
Actor
传统的并发是通过线程(thread)来实现的。在传统的并发模型中,程序被分成若干份同时执行的任务,并且所有任务都对一块共享的内存进行操作。在传统的并发模型会引起竞争问题,可以采取锁机制避免竞争问题,但同时这可能带来死锁等问题。
Actor模型是另一种不同的并发模型,它很好地解决了在传统并发模型中竞争和死锁等问题。我们可以把一个由actor模型实现的并发程序看成是一个星系一样,星系里面有很多星球,每个星球都是一个actor,星球之间不共享任何资源,但是它们之间有通道来相互传递信息。
每个星球(actor)都有一个信箱来接受来自其它星球的任意信息,它会按照信息接收的顺序来处理,处理完一个信息然后接着处理下一个信息。可以按照信息类型来触发不同的行为。
同时,每个星球(actor)可以异步地(也可以同步,但不是这里谈论的重点)向其它任意星球发送任意消息,就是说,它发送消息之后不会等待返回信息而是直接执行接下来的操作。
下面是一个Actor的例子:
import scala.actors.Actor
import scala.actors.Actor._
case class Increment(amount: Int)
case class Balance
class Account extends Actor {
var balance: Int = 0;
def act() = {
while (true) {
receive {
case Increment(amount) =>
balance += amount
case Balance =>
println("Balance is " + balance)
exit()
}
}
}
}
我们可以看到,程序里面定义两种不同的消息类型:Increment和Balance。Account是一个Actor,它跟外界的交互都是通过消息传递来实现:不论是increment,还是获取balance都是通过消息的方式来实现。当接受到不同的消息时,它会执行不同的行为。
我们也可以看到,Account的内部状态完全是自己控制的,接收到的消息是顺序执行的,所以我们不需要担心竞争问题。
小结
Scala就是这样,通过“使用基于事件的模型进行线程间通信”,并且“把不变对象作为消息进行传递”来实现一个并发编程模型。
--EOF--
分享到:
相关推荐
Scala并发编程是构建高效、可扩展的分布式系统的关键技术,特别是在大数据处理框架如Spark中。...掌握Scala并发编程和Akka的使用,对于理解和开发分布式系统,尤其是大数据处理应用,是至关重要的。
很大篇幅都放在,使用scala实现scala默认库文件的API中,通过对简单的函数式编程逻辑的介绍和实践,主要是实践,建立起来一个比较明晰的scala思维模式,或者叫函数式编程的思维模式。 2 无副作用的函数式编程,同时...
函数式代码易于测试和复用,容易实现并发,且不容易受到bug的攻击。Scala是一种能很好支持函数式编程的新兴JVM语言。《Scala函数式编程》是针对希望学习FP并将它应用于日常编码中的程序员而写的,内容包括:函数式...
用Scala开发并发编程。对scala和并发编程有兴趣想学习的同仁们下
Scala并发编程是高级函数式编程语言Scala...总之,Scala并发编程是现代软件开发中的重要技能,它结合了函数式编程的思维方式和并发处理的最佳实践。通过学习和实践,开发者可以构建出既高效又易于维护的并发应用程序。
读书笔记:scala并发编程
7. ** Actors模型**:Scala内置了Actors模型,用于并发编程,它基于消息传递,提供了一种安全的处理并发问题的方式。 8. **Akka框架**:虽然不是语言本身的一部分,但Akka是基于Scala构建的一个广泛使用的并发和...
Scala的出现主要是为了解决Java等传统编程语言在处理并发、复杂数据结构和模式匹配等方面的问题。它的设计目标是提高代码的可读性和可维护性,同时提供强大的类型系统和表达能力,使得编写高效、优雅的代码成为可能...
scala编程 33章 中文pdf Scala编程实战 目录 第1章字符串. 11 第2章数值39 第3章控制结构.60 第4章类和属性.103 第5章方法147 第6章对象170 第7章包和导入.190 第8章特质200 第9章函数式编程214 第10 章集合242 第...
Scala是一种多范式编程语言,它结合了面向对象编程和函数式编程的概念,设计目标是提供一种高效、简洁且可扩展的编程环境。本资源是一本高清版的Scala编程实战教程,适合对Scala有浓厚兴趣或者希望提升Scala技能的...
《SCALA程序设计-JAVA虚拟机多核编程实战》则专注于Scala在多线程和并发编程中的应用。书中可能详细讲解了Scala如何利用JVM的并行能力,比如使用 Futures 和 Promises 实现异步编程,通过 Actors 实现消息驱动的并发...
韩顺平老师的Scala语言核心编程教程可能会涵盖这些概念的详细解释,包括基本语法、面向对象和函数式编程的结合、类型系统、集合操作、并发编程等,对于初学者和进阶者来说都是很好的学习资源。通过阅读尚硅谷-韩顺平...
这些特性使得Scala成为处理并发和分布式计算的理想选择。 最后,通过实战示例和练习,读者将有机会实践所学知识,提升解决实际问题的能力。本书的第三版可能还包括了Scala语言的最新更新和改进,确保读者能够跟上...
Scala是一种静态类型的函数式编程语言,而Spark是一个分布式计算框架,尤其适合于大数据处理和分析。本教程将深入探讨这两者如何结合,实现高效的大数据分析、数据流处理以及机器学习任务。 首先,让我们来理解...
Scala是一种多范式编程语言,结合了面向对象编程和函数式编程的特点,运行在Java平台(JVM)上。它既能够提供静态类型检查的安全性,又能实现动态语言的灵活性。Scala的设计目标是解决Java的一些局限性,同时保持与...
Scala的设计目标是融合面向对象编程和函数式编程的最佳实践,提供一种既能够支持传统的对象模型,又可以进行高阶函数编程的语言。它的名字“Scala”恰好体现了这一核心理念,即“可伸缩性”,意味着它可以适应从小...
《Scala程序设计:Java虚拟机多核编程实战》是一本专为程序员和有经验的Java开发者设计的书籍,旨在引导读者掌握Scala语言,利用其功能强大的特性进行并发编程。Scala是一种融合了函数式和面向对象编程特点的静态...
4. ** Actors模型**:Scala内置对Akka库的支持,其中Actors模型提供了并发和分布式计算的解决方案。Actors是独立运行的单元,它们之间通过消息传递进行通信,确保了系统的线程安全。 5. **集合库**:Scala的集合库...