免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1921 | 回复: 0
打印 上一主题 下一主题

基于 Actor 模式并发的介绍 (Ruby) [复制链接]

论坛徽章:
49
15-16赛季CBA联赛之福建
日期:2016-06-22 16:22:002015年亚洲杯之中国
日期:2015-01-23 16:25:12丑牛
日期:2015-01-20 09:39:23未羊
日期:2015-01-14 23:55:57巳蛇
日期:2015-01-06 18:21:36双鱼座
日期:2015-01-02 22:04:33午马
日期:2014-11-25 09:58:35辰龙
日期:2014-11-18 10:40:07寅虎
日期:2014-11-13 22:47:15申猴
日期:2014-10-22 15:29:50摩羯座
日期:2014-08-27 10:49:43辰龙
日期:2014-08-21 10:47:58
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-02-21 09:36 |只看该作者 |倒序浏览
  
   
        
            
            
            
老一套的至理名言道,并发编程很难,在Ruby中尤其如此。就是这个基本假设,导致许多Ruby爱好者们对类似Erlang和Scala的语言发生了兴趣。为了让一般的程序员更加容易地实现和理解并发系统,这些语言内置了对
Actor模式
(Actor Model,或译为Actor模型)的支持。
            
但是,真的需要到Ruby语言之外寻找能够使你的工作变轻松的并发原语(Concurrency Primitive)吗?这个问题的答案可能取决于你所需要的并发和可用性的层次,但在近几年情况已经确定无疑地成型了。尤其是
Celluloid
框架,已经带给我们一种便捷、干净的方法,用来在Ruby中实现基于Actor模式的并发系统。
            
            
                    
   
   
        
            
            
            
为了领会Celluloid能为你做什么,首先你需要理解Actor模式是什么,以及同并发编程中传统的直接使用线程和锁的方式相比,Actor模式具有什么好处。在本文中,我们试图通过使用三种不同的方法解决同一个经典的并发谜题来弄清楚这些知识点。这三种方法是:使用Ruby内置的原语(线程和互斥锁)、使用Celluoid框架、使用一个我们从头创建的Actor模式的最小实现。
            
如果你现在还不是并发方面的专家,看完本文后当然也不会让你成为这样的专家,但能够使你在一些基本概念方面具有一个有利的开端,这些基本概念可以帮助你决定如何解决你自己项目中的并发编程问题。让我们开始吧!
            
            
                  
   
   
        
            
            
            哲学家就餐问题
            
哲学家就餐
问题是由Edsger Djisktra在1965年提出的,用来说明在多个进程为获得互斥性资源的使用权进行竞争时可能会出现哪些问题。
            
在这个问题中,五个哲学家正进行聚餐。他们坐在一个圆形餐桌周围,每个哲学家面前都有一碗米饭。另外还有五根筷子,每个哲学家一边一根。哲学家要花时间来思考人生的意义。无论何时只要他们饿了,他们就要试图吃饭。但是哲学家需要在每个手中都握有一根筷子才能弄到米饭吃。如果任何其他哲学家已经拿走了他所需要的两根筷子中的一根,那么这个饥饿的哲学家将会等待,直到那根被拿走的筷子可用为止。
            
这个问题令人关注是因为,如果不恰当地解决该问题,就能很容易地导致死锁问题。我们马上就会看看这些问题,但首先让我们把这个问题域(problem domain)转化为几个基本的Ruby对象。
            
            
                  
   
   
        
            
            
            对餐桌及其上的筷子进行建模
            
我们即将在本文中进行讨论的所有这三种解决办法都会用到筷子类Chopstic和餐桌类Table。这两个类的定义如下所示:
            
            
            
            
               
                    
                        01
                        class Chopstick
                    
               
            
            
            
            
               
                    
                        02
                        def initialize
                    
               
            
            
            
            
               
                    
                        03
                        @mutex = Mutex.new
                    
               
            
            
            
            
               
                    
                        04
                        end
                    
               
            
            
            
            
               
                    
                        05
                        
                    
               
            
            
            
            
               
                    
                        06
                        def take
                    
               
            
            
            
            
               
                    
                        07
                        @mutex.lock
                    
               
            
            
            
            
               
                    
                        08
                        end
                    
               
            
            
            
            
               
                    
                        09
                        
                    
               
            
            
            
            
               
                    
                        10
                        def drop
                    
               
            
            
            
            
               
                    
                        11
                        @mutex.unlock
                    
               
            
            
            
            
               
                    
                        12
                        
                    
               
            
            
            
            
               
                    
                        13
                        rescue ThreadError
                    
               
            
            
            
            
               
                    
                        14
                        puts "Trying to drop a chopstick not acquired"
                    
               
            
            
            
            
               
                    
                        15
                        end
                    
               
            
            
            
            
               
                    
                        16
                        
                    
               
            
            
            
            
               
                    
                        17
                        def in_use?
                    
               
            
            
            
            
               
                    
                        18
                        @mutex.locked?
                    
               
            
            
            
            
               
                    
                        19
                        end
                    
               
            
            
            
            
               
                    
                        20
                        end
                    
               
            
            
            
            
               
                    
                        21
                        
                    
               
            
            
            
            
               
                    
                        22
                        class Table
                    
               
            
            
            
            
               
                    
                        23
                        def initialize(num_seats)
                    
               
            
            
            
            
               
                    
                        24
                        @chopsticks = num_seats.times.map { Chopstick.new }
                    
               
            
            
            
            
               
                    
                        25
                        end
                    
               
            
            
            
            
               
                    
                        26
                        
                    
               
            
            
            
            
               
                    
                        27
                        def left_chopstick_at(position)
                    
               
            
            
            
            
               
                    
                        28
                        index = (position - 1) % @chopsticks.size
                    
               
            
            
            
            
               
                    
                        29
                        @chopsticks[index]
                    
               
            
            
            
            
               
                    
                        30
                        end
                    
               
            
            
            
            
               
                    
                        31
                        
                    
               
            
            
            
            
               
                    
                        32
                        def right_chopstick_at(position)
                    
               
            
            
            
            
               
                    
                        33
                        index = (position + 1) % @chopsticks.size
                    
               
            
            
            
            
               
                    
                        34
                        @chopsticks[index]
                    
               
            
            
            
            
               
                    
                        35
                        end
                    
               
            
            
            
            
               
                    
                        36
                        
                    
               
            
            
            
            
               
                    
                        37
                        def chopsticks_in_use
                    
               
            
            
            
            
               
                    
                        38
                        @chopsticks.select { |f| f.in_use? }.size
                    
               
            
            
            
            
               
                    
                        39
                        end
                    
               
            
            
            
            
               
                    
                        40
                        end
                    
               
            
            
            
            
            
Chopstick类仅仅是对普通的Ruby互斥锁(Mutex)进行了一个简单的封装, 该互斥锁将确保两个哲学家不能在同一时刻拿到同一根筷子。Table类处理谜题中的几何问题,它了解餐桌周围的每个座位在哪里,哪根筷子在某个座位的左边还是右边,它还知道当前有多少根筷子在使用中。
            
既然你已经看完了对此问题进行模型化后得到的基本领域对象(domain object),下面我们看看实现哲学家行为的不同的方法。我们将以不能正确解决问题的方法开始。
            
            
                    
   
   
        
            
            
            造成死锁的解决方案
            
以下所示的哲学家类,Philosopher,似乎是该问题最直截了当的一个解决方案了,但它有一个致命的缺陷,因此它不是一个线程安全的(Thread Safe)方案。你能找出这个缺陷吗?
            
            
            
            
               
                    
                        01
                        class Philosopher
                    
               
            
            
            
            
               
                    
                        02
                        def initialize(name)
                    
               
            
            
            
            
               
                    
                        03
                        @name = name
                    
               
            
            
            
            
               
                    
                        04
                        end
                    
               
            
            
            
            
               
                    
                        05
                        
                    
               
            
            
            
            
               
                    
                        06
                        def dine(table, position)
                    
               
            
            
            
            
               
                    
                        07
                        @left_chopstick = table.left_chopstick_at(position)
                    
               
            
            
            
            
               
                    
                        08
                        @right_chopstick = table.right_chopstick_at(position)
                    
               
            
            
            
            
               
                    
                        09
                        
                    
               
            
            
            
            
               
                    
                        10
                        loop do
                    
               
            
            
            
            
               
                    
                        11
                        think
                    
               
            
            
            
            
               
                    
                        12
                        eat
                    
               
            
            
            
            
               
                    
                        13
                        end
                    
               
            
            
            
            
               
                    
                        14
                        end
                    
               
            
            
            
            
               
                    
                        15
                        
                    
               
            
            
            
            
               
                    
                        16
                        def think
                    
               
            
            
            
            
               
                    
                        17
                        puts "#{@name} is thinking"
                    
               
            
            
            
            
               
                    
                        18
                        end
                    
               
            
            
            
            
               
                    
                        
                       
                               
                    
  • 共6页:

  • 上一页
    1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 下一页
                                   
                           
                           
                           
                                    时间:2013-02-21 08:55来源:开源中国社区 作者:oschina责任编辑:zhangkai

    本文来自ChinaUnix新闻频道,如果查看原文请点:http://news.chinaunix.net/opensource/2013/0221/2642628.shtml
  • 您需要登录后才可以回帖 登录 | 注册

    本版积分规则 发表回复

      

    北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
    未成年举报专区
    中国互联网协会会员  联系我们:huangweiwei@itpub.net
    感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

    清除 Cookies - ChinaUnix - Archiver - WAP - TOP