`
andyhu1007
  • 浏览: 193718 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Scala和并发编程

阅读更多

  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--

2
2
分享到:
评论

相关推荐

    scala并发编程开发教程

    Spark 的RPC是通过Akka类库实现的,Akka用Scala语言开发,基于Actor并发模型实现

    Scala函数式编程

    很大篇幅都放在,使用scala实现scala默认库文件的API中,通过对简单的函数式编程逻辑的介绍和实践,主要是实践,建立起来一个比较明晰的scala思维模式,或者叫函数式编程的思维模式。 2 无副作用的函数式编程,同时...

    Scala函数式编程.pdf

    函数式代码易于测试和复用,容易实现并发,且不容易受到bug的攻击。Scala是一种能很好支持函数式编程的新兴JVM语言。《Scala函数式编程》是针对希望学习FP并将它应用于日常编码中的程序员而写的,内容包括:函数式...

    Learning Concurrent Programming in Scala

    用Scala开发并发编程。对scala和并发编程有兴趣想学习的同仁们下

    scala编程中文pdf

    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并发编程程.rar

    学习scala并发的可以下载,需要一定scala基础 学习scala需要看scala编程或者scala编程思想

    Java虚拟机并发编程

    要重点强调的是,本书并不仅仅只适合于java语言的并发编程,它还适用于clojure、groovy、jruby和scala等所有运行在jvm平台上的编程语言。  《java虚拟机并发编程》共10章,分为五个部分。第一部分:并发策略,阐释...

    Scala程序设计_Java虚拟机多核编程实战

    本书循序渐进地介绍了Scala的函数式编程基础,虽然篇幅短小,却切中要害。读者可以学会使用Scala静态语言的强大功能创建简洁、可扩展、...对于多核时代JVM上的并发编程,Scala是绝好的工具,而本书是你必不可少的向导。

    Scala编程实战PDF

    本书向读者介绍如何省时省力地使用Scala构建面向对象、函数式、并发应用。书中囊括250个实用技巧以及700多个代码实例,覆盖了开始学习Scala语言、类库和工具时*常见的问题。本书可作为学习使用JVM语言的理想参考书,...

    scala编程实践

    Scala编程实战向读者介绍如何省时省力地使用Scala构建面向对象、函数式、并发应用。书中囊括250个实用技巧以及700多个代码实例,覆盖了开始学习Scala语言、类库和工具时*常见的问题。本书可作为学习使用JVM语言的...

    Scala编程实战

    本书向读者介绍如何省时省力地使用Scala构建面向对象、函数式、并发应用。书中囊括250个实用技巧以及700多个代码实例,覆盖了开始学习Scala语言、类库和工具时*常见的问题。本书可作为学习使用JVM语言的理想参考书,...

    Akka Scala 学习高清原版pdf

    Akka scala 并发 actor 高清原版pdf 学习scala实现akka进行并发编程

    zio:ZIO —一种类型安全的可组合库,用于Scala中的异步和并发编程

    ZIO是用于异步和并发编程的零依赖Scala库。 ZIO由永不浪费或泄漏资源的高度可扩展的无阻塞光纤驱动,可让您构建可扩展的,灵活的,React灵敏的应用程序,以满足您的业务需求。 高性能。 使用Scala Future 100倍...

    spark源码之scala基础语法demo

    scala是一种基于JVM的面向对象的函数编程,scala编程相对于java而言代码整洁、开发效率更高。 其中scala优点主要有: 1:面向对象,可以定义class,通过new调用实例对象使用。 2:兼容java,在scala中可以直接调用...

    concurrency-in-scala-with-ce:基于cats-effect库的Scala中异步和并发编程概念简介

    但是,这里介绍的许多概念不仅适用于其他Scala效果库,还适用于处理并发和异步编程的任何系统或编程语言。 注意:应该指出的是,本文的目的不是提供“更好的文档”。首先,因为有关该主题的现有材料已经很不错了(您...

    scala-2.13.1.tgz

    Scala是一门以Java虚拟机(JVM)为目标运行环境并将面向对象和函数式编程语言的最佳特性结合在一起的编程语言。你可以使用Scala编写出更加精简的程序,同时充分利用并发的威力。由于Scala运行于JVM之上,因此它可以...

    Scala编程实战.rar

    scala基础语法,字符串,数值,控制结构,类和属性,方法,对象,包和导入,特质,函数式编程,集合。列表,数组,映射,文件和进程,Actors和并发,命令行执行,

Global site tag (gtag.js) - Google Analytics