Tải bản đầy đủ

Programming erlang, 2nd edition

www.it-ebooks.info


www.it-ebooks.info


Early Praise for

Programming Erlang, Second Edition
This second edition of Joe’s seminal Programming Erlang is a welcome update,
covering not only the core language and framework fundamentals but also key
community projects such as rebar and cowboy. Even experienced Erlang programmers will find helpful tips and new insights throughout the book, and beginners
to the language will appreciate the clear and methodical way Joe introduces and
explains key language concepts.
➤ Alexander Gounares
Former AOL CTO, advisor to Bill Gates, and founder/CEO of Concurix Corp.
A gem; a sensible, practical introduction to functional programming.
➤ Gilad Bracha
Coauthor of the Java language and Java Virtual Machine specifications, creator
of the Newspeak language, member of the Dart language team
Programming Erlang is an excellent resource for understanding how to program

with Actors. It’s not just for Erlang developers, but for anyone who wants to
understand why Actors matters and why they are such an important tool in
building reactive, scalable, resilient, and event-driven systems.
➤ Jonas Bonér
Creator of the Akka Project and the AspectWerkz Aspect-Oriented Programming
(AOP) framework, co-founder and CTO of Typesafe

www.it-ebooks.info


Programming Erlang, Second Edition
Software for a Concurrent World

Joe Armstrong

The Pragmatic Bookshelf
Dallas, Texas • Raleigh, North Carolina

www.it-ebooks.info


Many of the designations used by manufacturers and sellers to distinguish their products
are claimed as trademarks. Where those designations appear in this book, and The Pragmatic
Programmers, LLC was aware of a trademark claim, the designations have been printed in
initial capital letters or in all capitals. The Pragmatic Starter Kit, The Pragmatic Programmer,
Pragmatic Programming, Pragmatic Bookshelf, PragProg and the linking g device are trademarks of The Pragmatic Programmers, LLC.
Every precaution was taken in the preparation of this book. However, the publisher assumes
no responsibility for errors or omissions, or for damages that may result from the use of
information (including program listings) contained herein.
Our Pragmatic courses, workshops, and other products can help you and your team create
better software and have more fun. For more information, as well as the latest Pragmatic
titles, please visit us at http://pragprog.com.
The team that produced this book includes:
Susannah Davidson Pfalzer (editor)
Potomac Indexing, LLC (indexer)
Kim Wimpsett (copyeditor)
David J Kelly (typesetter)
Janet Furlow (producer)
Juliet Benda (rights)
Ellie Callahan (support)



Copyright © 2013 Pragmatic Programmers, LLC.
All rights reserved.

No part of this publication may be reproduced, stored in a retrieval system, or
transmitted, in any form, or by any means, electronic, mechanical, photocopying,
recording, or otherwise, without the prior consent of the publisher.
Printed in the United States of America.
ISBN-13: 978-1-937785-53-6
Encoded using the finest acid-free high-entropy binary digits.
Book version: P1.0—August 2013

www.it-ebooks.info


Contents
Introduction

.

.

.

.

.

.

.

.

.

.

.

.

xiii

Part I — Why Erlang?
1.

Introducing Concurrency .
.
.
.
.
.
.
.
1.1 Modeling Concurrency
1.2 Benefits of Concurrency
1.3 Concurrent Programs and Parallel Computers
1.4 Sequential vs. Concurrent Programming Languages

2.

A Whirlwind Tour of Erlang .
.
.
.
2.1 The Shell
2.2 Processes, Modules, and Compilation
2.3 Hello, Concurrency

.

.

.

3
3
6
8
9

.

.

.

.

11
11
13
15

Part II — Sequential Programming
3.

Basic Concepts .
.
.
.
.
.
.
.
3.1 Starting and Stopping the Erlang Shell
3.2 Simple Integer Arithmetic
3.3 Variables
3.4 Floating-Point Numbers
3.5 Atoms
3.6 Tuples
3.7 Lists
3.8 Strings
3.9 Pattern Matching Again

.

.

.

.

25
25
27
28
32
33
34
37
39
41

4.

Modules and Functions .
.
.
.
.
4.1 Modules Are Where We Store Code
4.2 Back to Shopping

.

.

.

.

43
43
50

www.it-ebooks.info

.


Contents

4.3
4.4
4.5
4.6
4.7
4.8
4.9
4.10

Funs: The Basic Unit of Abstraction
Simple List Processing
List Comprehensions
BIFs
Guards
case and if Expressions
Building Lists in Natural Order
Accumulators

5.

Records and Maps
.
.
.
.
.
.
5.1 When to Use Maps or Records
5.2 Naming Tuple Items with Records
5.3 Maps: Associative Key-Value Stores

6.

Error
6.1
6.2
6.3
6.4
6.5
6.6

7.

Binaries and the Bit Syntax .
.
.
.
7.1 Binaries
7.2 The Bit Syntax
7.3 Bitstrings: Processing Bit-Level Data

8.

The Rest of Sequential Erlang .
.
.
.
8.1 apply
8.2 Arithmetic Expressions
8.3 Arity
8.4 Attributes
8.5 Block Expressions
8.6 Booleans
8.7 Boolean Expressions
8.8 Character Set
8.9 Comments
8.10 Dynamic Code Loading
8.11 Erlang Preprocessor
8.12 Escape Sequences
8.13 Expressions and Expression Sequences

• vi
52
57
59
63
64
68
70
71

.

.

.

.

.

75
75
76
79

Handling in Sequential Programs .
.
Handling Errors in Sequential Code
Trapping an Exception with try…catch
Trapping an Exception with catch
Programming Style with Exceptions
Stack Traces
Fail Fast and Noisily, Fail Politely

.

.

.

.

87
88
89
92
93
95
96

.

.

.

.

99
99
101
110

www.it-ebooks.info

.

.

.

.

.

113
115
116
116
117
120
120
121
122
122
122
126
126
127


Contents

8.14
8.15
8.16
8.17
8.18
8.19
8.20
8.21
8.22
8.23
8.24
8.25
8.26
9.

Function References
Include Files
List Operations ++ and - Macros
Match Operator in Patterns
Numbers
Operator Precedence
The Process Dictionary
References
Short-Circuit Boolean Expressions
Term Comparisons
Tuple Modules
Underscore Variables

• vii

128
128
129
129
131
132
133
134
135
135
136
137
137

Types .
.
.
.
.
.
.
.
.
9.1 Specifying Data and Function Types
9.2 Erlang Type Notation
9.3 A Session with the Dialyzer
9.4 Type Inference and Success Typing
9.5 Limitations of the Type System

.

10. Compiling and Running Your Program .
.
10.1 Modifying the Development Environment
10.2 Different Ways to Run Your Program
10.3 Automating Compilation with Makefiles
10.4 When Things Go Wrong
10.5 Getting Help
10.6 Tweaking the Environment

.

.

.

.

141
141
143
148
152
155

.

.

.

.

159
159
161
166
169
172
173

Part III — Concurrent and Distributed Programs
11. Real-World Concurrency

.

.

.

.

.

.

.

.

.

177

12. Concurrent Programming .
.
12.1 The Concurrency Primitives
12.2 Introducing Client-Server
12.3 Processes Are Cheap
12.4 Receive with a Timeout
12.5 Selective Receive
12.6 Registered Processes

.

.

.

.

.

.

.

181
182
184
189
191
193
194

www.it-ebooks.info


Contents

12.7 A Word About Tail Recursion
12.8 Spawning with MFAs or Funs

• viii

196
197

13. Errors in Concurrent Programs .
.
.
.
.
13.1 Error Handling Philosophy
13.2 Error Handling Semantics
13.3 Creating Links
13.4 Groups of Processes That All Die Together
13.5 Setting Up a Firewall
13.6 Monitors
13.7 Error Handling Primitives
13.8 Programming for Fault Tolerance

.

.

.

199
199
202
203
204
205
205
206
207

14. Distributed Programming .
.
.
.
.
.
.
14.1 Two Models for Distribution
14.2 Writing a Distributed Program
14.3 Building the Name Server
14.4 Libraries and BIFS for Distributed Programming
14.5 The Cookie Protection System
14.6 Socket-Based Distribution

.

.

211
212
213
213
219
222
224

15. Interfacing Techniques .
.
.
.
.
.
.
.
.
15.1 How Erlang Communicates with External Programs
15.2 Interfacing an External C Program with a Port
15.3 Calling a Shell Script from Erlang
15.4 Advanced Interfacing Techniques

.

231
232
234
240
240

16. Programming with Files
.
.
.
16.1 Modules for Manipulating Files
16.2 Ways to Read a File
16.3 Ways to Write a File
16.4 Directory and File Operations
16.5 Bits and Pieces
16.6 A Find Utility

.

.

.

.

.

.

243
243
244
251
255
258
258

17. Programming with Sockets .
.
17.1 Using TCP
17.2 Active and Passive Sockets
17.3 Error Handling with Sockets

.

.

.

.

.

.

263
263
272
275

Part IV — Programming Libraries and Frameworks

.

www.it-ebooks.info


Contents

17.4 UDP
17.5 Broadcasting to Multiple Machines
17.6 A SHOUTcast Server

• ix

276
280
281

18. Browsing with Websockets and Erlang .
18.1 Creating a Digital Clock
18.2 Basic Interaction
18.3 An Erlang Shell in the Browser
18.4 Creating a Chat Widget
18.5 IRC Lite
18.6 Graphics in the Browser
18.7 The Browser Server Protocol

.

.

.

.

.

287
288
291
292
293
295
299
301

19. Storing Data with ETS and DETS
.
.
19.1 Types of Table
19.2 ETS Table Efficiency Considerations
19.3 Creating an ETS Table
19.4 Example Programs with ETS
19.5 Storing Tuples on Disk
19.6 What Haven’t We Talked About?

.

.

.

.

.

305
306
308
309
310
315
318

20. Mnesia: The Erlang Database
.
.
.
.
.
20.1 Creating the Initial Database
20.2 Database Queries
20.3 Adding and Removing Data in the Database
20.4 Mnesia Transactions
20.5 Storing Complex Data in Tables
20.6 Table Types and Location
20.7 The Table Viewer
20.8 Digging Deeper

.

.

.

321
321
322
326
328
332
333
336
337

21. Profiling, Debugging, and Tracing .
.
.
21.1 Tools for Profiling Erlang Code
21.2 Testing Code Coverage
21.3 Generating Cross-References
21.4 Compiler Diagnostics
21.5 Runtime Diagnostics
21.6 Debugging Techniques
21.7 The Erlang Debugger
21.8 Tracing Messages and Process Execution
21.9 Frameworks for Testing Erlang Code

.

.

.

339
340
341
342
343
346
347
350
352
355

www.it-ebooks.info

.


Contents

•x

22. Introducing OTP
.
.
.
.
.
.
22.1 The Road to the Generic Server
22.2 Getting Started with gen_server
22.3 The gen_server Callback Structure
22.4 Filling in the gen_server Template
22.5 Digging Deeper

.

.

.

.

.

359
360
368
372
376
377

23. Making a System with OTP .
.
.
23.1 Generic Event Handling
23.2 The Error Logger
23.3 Alarm Management
23.4 The Application Servers
23.5 The Supervision Tree
23.6 Starting the System
23.7 The Application
23.8 File System Organization
23.9 The Application Monitor
23.10 How Did We Make That Prime?
23.11 Digging Deeper

.

.

.

.

.

381
382
384
392
394
396
400
403
405
406
407
409

24. Programming Idioms
.
.
.
.
.
.
.
24.1 Maintaining the Erlang View of the World
24.2 A Multipurpose Server
24.3 Stateful Modules
24.4 Adapter Patterns
24.5 Intentional Programming

.

.

.

413
413
416
418
419
422

.

Part V — Building Applications

25. Third-Party Programs .
.
.
.
.
.
.
.
.
.
25.1 Making a Shareable Archive and Managing Your Code with
Rebar
25.2 Integrating External Programs with Our Code
25.3 Making a Local Copy of the Dependencies
25.4 Building Embedded Web Servers with Cowboy
26. Programming Multicore CPUs .
.
.
.
.
.
.
.
26.1 Good News for Erlang Programmers
26.2 How to Make Programs Run Efficiently on a Multicore
CPU
26.3 Parallelizing Sequential Code

www.it-ebooks.info

425
425
428
430
431
439
440
441
445


Contents

26.4 Small Messages, Big Computations
26.5 Parallelizing Computations with mapreduce

• xi

447
451

27. Sherlock’s Last Case
.
.
.
.
.
.
27.1 Finding Similarities in Data
27.2 A Session with Sherlock
27.3 The Importance of Partitioning the Data
27.4 Adding Keywords to the Postings
27.5 Overview of the Implementation
27.6 Exercises
27.7 Wrapping Up

.

.

.

.

457
458
458
463
464
467
469
470

A1. OTP Templates .
.
.
.
.
.
A1.1 The Generic Server Template
A1.2 The Supervisor Template
A1.3 The Application Template

.

.

.

.

.

.

471
471
474
475

A2. A Socket Application
.
A2.1 An Example
A2.2 How lib_chan Works
A2.3 The lib_chan Code

.

.

.

.

.

.

477
477
479
483

A3. A Simple Execution Environment .
.
.
A3.1 How Erlang Starts
A3.2 Running Some Test Programs in SEE
A3.3 The SEE API
A3.4 SEE Implementation Details
A3.5 How Code Gets Loaded in Erlang

.

.

.

.

493
494
496
499
500
508

.

.

.

.

511

Index

.

.

.

.

.

.

.

.

.

.

.

www.it-ebooks.info

.

.


Introduction
New hardware is increasingly parallel, so new programming languages must
support concurrency or they will die.
“The way the processor industry is going is to add more and more cores, but
nobody knows how to program those things. I mean, two, yeah; four, not really;
eight, forget it.” —Steve Jobs, Apple 1

Well, Steve was wrong; we do know how to program multicores. We program
them in Erlang, and many of our programs just go faster as we add more
cores.
Erlang was designed from the bottom up to program concurrent, distributed,
fault-tolerant, scalable, soft, real-time systems. Soft real-time systems are
systems such as telephone exchanges, banking systems, and so on, where
rapid response times are important but it’s not a disaster if the odd timing
deadline is missed. Erlang systems have been deployed on a massive scale
and control significant parts of the world’s mobile communication networks.
If your problem is concurrent, if you are building a multiuser system, or if
you are building a system that evolves with time, then using Erlang might
save you a lot of work, since Erlang was explicitly designed for building such
systems.
“It’s the mutable state, stupid.” —Brian Goetz, Java Concurrency in Practice

Erlang belongs to the family of functional programming languages. Functional
programming forbids code with side effects. Side effects and concurrency
don’t mix. In Erlang it’s OK to mutate state within an individual process but
not for one process to tinker with the state of another process. Erlang has no
mutexes, no synchronized methods, and none of the paraphernalia of shared
memory programming.

1.

http://bits.blogs.nytimes.com/2008/06/10/apple-in-parallel-turning-the-pc-world-upside-down/

www.it-ebooks.info

report erratum • discuss


Introduction

• xiv

Processes interact by one method, and one method only, by exchanging
messages. Processes share no data with other processes. This is the reason
why we can easily distribute Erlang programs over multicores or networks.
When we write an Erlang program, we do not implement it as a single process
that does everything; we implement it as large numbers of small processes
that do simple things and communicate with each other.

What’s This Book About?
It’s about concurrency. It’s about distribution. It’s about fault tolerance. It’s
about functional programming. It’s about programming a distributed concurrent system without locks and mutexes but using only pure message passing.
It’s about automatically speeding up your programs on multicore CPUs. It’s
about writing distributed applications that allow people to interact with each
other. It’s about design patterns for writing fault-tolerant and distributed
systems. It’s about modeling concurrency and mapping those models onto
computer programs, a process I call concurrency-oriented programming.

Who Is This Book For?
The target audience for this book ranges from the experienced Erlang programmer who wants to learn more about Erlang internals and the philosophy
behind Erlang to the absolute beginner. The text has been reviewed by programmers at all levels, from expert to beginner. One of the major differences
between the second and first editions has been the addition of a large amount
of explanatory material especially targeted at the beginner. Advanced Erlang
programmers can skip over the introductory material.
A second goal has been to demystify functional, concurrent, and distributed
programming and present it in a way that is appropriate to an audience that
has no prior knowledge of concurrency or functional programming. Writing
functional programs and parallel programs has long been regarded as a “black
art”; this book is part of an ongoing attempt to change this.
While this book assumes no specific knowledge of either functional or concurrent programming, it is addressed to somebody who already is familiar with
one or two programming languages.
When you come to a new programming language, it’s often difficult to think
of “problems that are suitable for solution in the new language.” The exercises
give you a clue. These are the kind of problems that are suitably solved in
Erlang.

www.it-ebooks.info

report erratum • discuss


New in This Edition

• xv

New in This Edition
First, the text has been brought up-to-date to reflect all the changes made to
Erlang since the first edition of the book was published. We now cover all
official language changes and describe Erlang version R17.
The second edition has been refocused to address the needs of beginners,
with more explanatory text than in the first edition. Material intended for
advanced users, or that might change rapidly, has been moved to online
repositories.
The programming exercises proved so popular in the first edition that exercises
now appear at the end of each chapter. The exercises vary in complexity, so
there’s something for both beginner users and advanced users.
In several completely new chapters, you’ll learn about the Erlang type system
and the Dialyzer, maps (which are new to Erlang, as of R17), websockets,
programming idioms, and integrating third-party code. A new appendix
describes how to build a minimal stand-alone Erlang system.
The final chapter, “Sherlock’s Last Case,” is a new chapter that gives you an
exercise in processing and extracting meaning from a large volume of text.
This is an open-ended chapter, and I hope that the exercises at the end of
this chapter will stimulate future work.

Road Map
You can’t run until you can walk. Erlang programs are made up from lots of
small sequential programs running at the same time. Before we can write
concurrent code, we need to be able to write sequential code. This means we
won’t get into the details of writing concurrent programs until Chapter 11,
Real-World Concurrency, on page 177.
• Part I has a short introduction to the central ideas of concurrent programming and a whirlwind tour of Erlang.
• Part II covers sequential Erlang programming in detail and also talks
about types and methods for building Erlang programs.
• Part III is the core of the book where we learn about how to write concurrent and distributed Erlang programs.
• Part IV covers the major Erlang libraries, techniques for tracing and
debugging, and techniques for structuring Erlang code.
• Part V covers applications. You’ll learn how to integrate external software
with the core Erlang libraries and how to turn your own code into open

www.it-ebooks.info

report erratum • discuss


Introduction

• xvi

source contributions. We’ll talk about programming idioms and how to
program multicore CPUs. And finally, Sherlock Holmes will analyze our
thoughts.
At the end of each chapter, you’ll find a selection of programming exercises.
These are to test your knowledge of the chapter and to challenge you. The
problems vary from easy to difficult. The most difficult problems would be
suitable research projects. Even if you don’t try to solve all the problems, just
thinking about the problems and how you would solve them will enhance
your understanding of the text.

The Code in This Book
Most of the code snippets come from full-length, running examples that you
can download.2 To help you find your way, if a code listing in this book can
be found in the download, there’ll be a bar above the snippet (just like the
one here):
shop1.erl
-module(shop1).
-export([total/1]).
total([{What, N}|T]) -> shop:cost(What) * N + total(T);
total([])
-> 0.

This bar contains the path to the code within the download. If you’re reading
the ebook version of this book and your ebook reader supports hyperlinks,
you can click the bar, and the code should appear in a browser window.

Help! It Doesn’t Work
Learning new stuff is difficult. You will get stuck. When you get stuck, rule
1 is to not silently give up. Rule 2 is to get help. Rule 3 is to ask Sherlock.
Rule 1 is important. There are people who have tried Erlang, gotten stuck
and given up, and not told anybody. If we don’t know about a problem, we
can’t fix it. End of story.
The best way to get help is to first try Google; if Google can’t help, send mail
to the Erlang mailing list.3 You can also try #erlounge or #erlang at irc.freenode.net
for a faster response.
Sometimes the answer to your question might be in an old posting to the
Erlang mailing list but you just can’t find it. In Chapter 27, Sherlock's Last
2.
3.

http://www.pragprog.com/titles/jaerlang2/source_code
erlang-questions@erlang.org

www.it-ebooks.info

report erratum • discuss


Acknowledgments

• xvii

Case, on page 457, there’s a program you can run locally that can perform
sophisticated searches on all the old postings to the Erlang mailing list.
So, without further ado, I’ll thank the good folks who helped me write this
book (and the first edition), and you can skip on to Chapter 1, where we’ll
take a lightning tour of Erlang.

Acknowledgments
First Edition
Many people helped in the preparation of this book, and I’d like to thank them
all here.
First, Dave Thomas, my editor: Dave taught me to write and subjected me to
a barrage of never-ending questions. Why this? Why that? When I started the
book, Dave said my writing style was like “standing on a rock preaching.” He
said, “I want you to talk to people, not preach.” The book is better for it.
Thanks, Dave.
Next, I had a little committee of language experts at my back. They helped
me decide what to leave out. They also helped me clarify some of the bits that
are difficult to explain. Thanks here (in no particular order) to Björn Gustavsson, Robert Virding, Kostis Sagonas, Kenneth Lundin, Richard Carlsson, and
Ulf Wiger.
Thanks also to Claes Vikström who provided valuable advice on Mnesia, to
Rickard Green who gave information on SMP Erlang, and to Hans Nilsson for
the stemming algorithm used in the text-indexing program.
Sean Hinde and Ulf Wiger helped me understand how to use various OTP
internals, and Serge Aleynikov explained active sockets to me so that I could
understand.
Helen Taylor (my wife) proofread several chapters and provided hundreds of
cups of tea at appropriate moments. What’s more, she put up with my rather
obsessive behavior for seven months. Thanks also to Thomas and Claire; and
thanks to Bach and Handel, my cats Zorro and Daisy, and my Sat Nav Doris,
who helped me stay sane, purred when stroked, and got me to the right
addresses.
Finally, to all the readers of the beta book who filled in errata requests: I have
cursed you and praised you. When the first beta went out, I was unprepared
for the entire book to be read in two days and for you to shred every page
with your comments. But the process has resulted in a much better book

www.it-ebooks.info

report erratum • discuss


Introduction

• xviii

than I had imagined. When (as happened several times) dozens of people said,
“I don’t understand this page,” then I was forced to think again and rewrite
the material concerned. Thanks for your help, everybody.

Second Edition
First, my new editor, Susannah Pfalzer, helped a lot in suggesting new ways
to reorganize and refocus the book. It was great working with you; you’ve
taught me a lot.
Kenneth Lundin and the guys in the OTP group worked hard to deliver the
new language features described in the second edition.
Many readers of the first edition provided feedback on things they didn’t
understand, so I hope these are now rectified.
The design of maps is inspired by the work of Richard A. O’Keefe (who called
them frames). Richard has championed the cause of frames on the Erlang
mailing list for many years. Thanks, Richard, for all your comments and
suggestions.
Kostis Sagonas provided lots of helpful feedback on the treatment of the type
system.
I’d also like to thank Loïc Hoguin for his permission to use some examples
from the cowboy web server from Nine Nines and the guys from Basho who
wrote the code for BitLocker. I’d also like to thank Dave Smith for his work
with rebar.
A number of people helped me by reviewing various drafts of the second edition. I’d like to thank all of them; they made this a better book. So, thanks
to Erik Abefelt, Paul Butcher, Mark Chu-Carroll, Ian Dees, Henning Diedrich,
Jeremy Frens, Loïc Hoguin, Andy Hunt, Kurt Landrus, Kenneth Lundin, Evan
Miller, Patrik Nyblom, Tim Ottinger, Kim Shrier, and Bruce Tate for your help.
Helen Taylor (Twitter @mrsjoeerl) made countless cups of tea and cheered me
up when I thought the book would never get finished.
Gustav Mahler, Sergei Rachmaninoff, Richard Wagner, and George Frideric
Handel composed music (and Bob Dylan and few other guys…) that I played
in the background while writing much of this book.

www.it-ebooks.info

report erratum • discuss


Part I

Why Erlang?

We introduce concurrency and talk about the difference between concurrency and parallelism. You’ll
learn about the benefits of writing concurrent
programs and take a whirlwind tour of Erlang,
introducing the main features of the language.

www.it-ebooks.info


CHAPTER 1

Introducing Concurrency
Let’s forget about computers for a moment; I’m going to look out of my window
and tell you what I see.
I see a woman taking a dog for a walk. I see a car trying to find a parking
space. I see a plane flying overhead and a boat sailing by. All these things
happen in parallel. In this book, we will learn how to describe parallel activities
as sets of communicating parallel processes. We will learn how to write concurrent programs.
In everyday language, words like concurrent, simultaneous, and parallel mean
almost the same thing. But in programming languages, we need to be more
precise. In particular, we need to distinguish between concurrent and parallel
programs.
If we have only a single-core computer, then we can never run a parallel
program on it. This is because we have one CPU, and it can do only one thing
at a time. We can, however, run concurrent programs on a single-core computer. The computer time-shares between the different tasks, maintaining
the illusion that the different tasks run in parallel.
In the following sections, we’ll start with some simple concurrency modeling,
move on to see the benefits of solving problems using concurrency, and
finally look at some precise definitions that highlight the differences between
concurrency and parallelism.

1.1

Modeling Concurrency
We’ll start with a simple example and build a concurrent model of an everyday
scene. Imagine I see four people out for a walk. There are two dogs and a large
number of rabbits. The people are talking to each other, and the dogs want
to chase the rabbits.

www.it-ebooks.info

report erratum • discuss


Chapter 1. Introducing Concurrency

•4

To simulate this in Erlang, we’d make four modules called person, dog, rabbit,
and world. The code for person would be in a file called person.erl and might look
something like this:
-module(person). export([init/1]).
init(Name) -> ...

The first line, -module(person)., says that this file contains code for the module
called person. This should be the same as the filename (excluding the .erl filename extension). The module name must start with a small letter. Technically,
the module name is an atom; we’ll talk more about atoms in Section 3.5,
Atoms, on page 33.
Following the module declaration is an export declaration. The export declarations tells which functions in the module can be called from outside the
module. They are like public declarations in many programming languages.
Functions that are not in an export declaration are private and cannot be
called from outside the module.
The syntax -export([init/1]). means the function init with one argument (that’s
what /1 means; it does not mean divide by one) can be called from outside the
module. If we want to export several functions, we’d use this syntax:
-export([FuncName1/N1, FuncName2/N2, .....]).

The square brackets [ ... ] mean “list of,” so this declaration means we want
to export a list of functions from the module.
We’d write similar code for dog and rabbit.

Starting the Simulation
To start the program, we’ll call world:start(). This is defined in a module called
world, which begins like this:
-module(world). export([start/0]).
start() ->
Joe
Susannah
Dave
Andy
Rover
...
Rabbit1
...

=
=
=
=
=

spawn(person,
spawn(person,
spawn(person,
spawn(person,
spawn(dog,

init,
init,
init,
init,
init,

["Joe"]),
["Susannah"]),
["Dave"]),
["Andy"]),
["Rover"]),

= spawn(rabbit, init, ["Flopsy"]),

www.it-ebooks.info

report erratum • discuss


Modeling Concurrency

•5

spawn is an Erlang primitive that creates a concurrent process and returns a

process identifier. spawn is called like this:
spawn(ModName, FuncName, [Arg1, Arg2, ..., ArgN])

When spawn is evaluated, the Erlang runtime system creates a new process
(not an operating system process but a lightweight process that is managed
by the Erlang system). Once the process has been created, it starts evaluating
the code specified by the arguments. ModName is the name of the module that
has the code we want to execute. FuncName is the name of the function in the
module, and [Arg1, Arg2, …] is a list containing the arguments to the function
that we want to evaluate. Thus, the following call means start a process that
evaluates the function person:init("Joe"):
spawn(person, init, ["Joe"])

The return value of spawn is a process identifier (PID) that can be used to
interact with the newly created process.

Analogy with Objects
Modules in Erlang are like classes in an object-oriented programming language
(OOPL), and processes are like objects (or class instances) in an OOPL.
In Erlang, spawn creates a new process by running a function defined in a module. In
Java, new creates a new object by running a method defined in a class.
In an OOPL we can have one class but several thousand class instances. Similarly,
in Erlang we can have one module but thousands or even millions of processes that
execute the code in the module. All the Erlang processes execute concurrently and
independently and, if we had a million-core computer, might even run in parallel.

Sending Messages
Once our simulation has been started, we’ll want to send messages between
the different processes in the program. In Erlang, processes share no memory
and can interact only with each other by sending messages. This is exactly
how objects in the real world behave.
Suppose Joe wants to say something to Susannah. In the program we’d write
a line of code like this:
Susannah ! {self(), "Hope the dogs don't chase the rabbits"}

The syntax Pid ! Msg means send the message Msg to the process Pid. The self()
argument in the curly brackets identifies the process sending the message (in
this case Joe).

www.it-ebooks.info

report erratum • discuss


Chapter 1. Introducing Concurrency

•6

Receiving Messages
For Susannah’s process to receive the message from Joe, we’d write this:
receive
{From, Message} ->
...
end

When Susannah’s process receives a message, the variable From will be bound
to Joe so that Susannah knows who the message came from, and the variable
Message will contain the message.
We could imagine extending our model by having the dogs send “woof woof
rabbits” messages to each other and the rabbits sending “panic go and hide”
messages to each other.
The key point we should remember here is that our programming model is
based on observation of the real world. We have three modules (person, dog,
and rabbit) because there are three types of concurrent things in our example.
The world module is needed for a top-level process to start everything off. We
created two dog processes because there are two dogs, and we created four
people processes because there were four people. The messages in the program
reflect the observed messages in our example.
Rather than extending the model, we’ll stop at this point, change gears, and
look at some of the characteristics of concurrent programs.

1.2

Benefits of Concurrency
Concurrent programming can be used to improve performance, to create
scalable and fault-tolerant systems, and to write clear and understandable
programs for controlling real-world applications. The following are some of
the reasons why this is true:
Performance
Imagine you have two tasks: A, which takes ten seconds to perform, and
B, which takes fifteen seconds. On a single CPU doing both, A and B will
take twenty-five seconds. On a computer with two CPUs that operate
independently, doing A and B will take only fifteen seconds. To achieve
this performance improvement, we have to write a concurrent program.
Until recently, parallel computers were rare and expensive, but today
multicore computers are commonplace. A top-end processor has sixtyfour cores, and we can expect the number of cores per chip to steadily
increase in the foreseeable future. If you have a suitable problem and a

www.it-ebooks.info

report erratum • discuss


Benefits of Concurrency

•7

computer with sixty-four cores, your program might go sixty-four times
faster when run on this computer, but only if you write a concurrent
program.
One of the most pressing problems in the computer industry is caused
by difficulties in parallelizing legacy sequential code so it can run on a
multicore computer. There is no such problem in Erlang. Erlang programs
written twenty years ago for a sequential machine now just run faster
when we run them on modern multicores.
Scalability
Concurrent programs are made from small independent processes.
Because of this, we can easily scale the system by increasing the number
of processes and adding more CPUs. At runtime the Erlang virtual machine
automatically distributes the execution of processes over the available
CPUs.
Fault tolerance
Fault tolerance is similar to scalability. The keys to fault tolerance are
independence and hardware redundancy. Erlang programs are made up
of many small independent processes. Errors in one process cannot
accidentally crash another process. To protect against the failure of an
entire computer (or data center), we need to detect failures in remote
computers. Both process independence and remote failure detection are
built into the Erlang VM.
Erlang was designed for building fault-tolerant telecommunications systems, but the same technology can be applied equally well to building
fault-tolerant scalable web systems or cloud services.
Clarity
In the real world things happen in parallel, but in most programming
languages things happen sequentially. The mismatch between the parallelism in the real world and the sequentiality in our programming
languages makes writing real-world control problems in a sequential
language artificially difficult.
In Erlang we can map real-world parallelism onto Erlang concurrency in
a straightforward manner. This results in clear and easily understood
code.
Now that you’ve seen these benefits, we’ll try to add some precision to the
notion of concurrency and parallelism. This will give us a framework to talk
about these terms in future chapters.

www.it-ebooks.info

report erratum • discuss


Chapter 1. Introducing Concurrency

1.3

•8

Concurrent Programs and Parallel Computers
I’m going to be pedantic here and try to give precise meanings to terms such
as concurrent and parallel. We want to draw the distinction between a concurrent program, which is something that could potentially run faster if we had
a parallel computer, and a parallel computer that really has more than one
core (or CPU).
• A concurrent program is a program written in a concurrent programming
language. We write concurrent programs for reasons of performance,
scalability, or fault tolerance.
• A concurrent programming language is a language that has explicit language constructs for writing concurrent programs. These constructs are
an integral part of the programming language and behave the same way
on all operating systems.
• A parallel computer is a computer that has several processing units (CPUs
or cores) that run at the same time.
Concurrent programs in Erlang are made from sets of communicating
sequential processes. An Erlang process is a little virtual machine that can
evaluate a single Erlang function; it should not be confused with an operating
system process.
To write a concurrent program in Erlang, you must identify a set of processes
that will solve your problem. We call this act of identifying the processes
modeling concurrency. This is analogous to the art of identifying the objects
that are needed to write an objected-oriented program.
Choosing the objects that are needed to solve a problem is recognized as being
a hard problem in object-oriented design. The same is true in modeling concurrency. Choosing the correct processes can be difficult. The difference
between a good and bad process model can make or break a design.
Having written a concurrent program, we can run it on a parallel computer.
We can run on a multicore computer or on a set of networked computers or
in the cloud.
Will our concurrent program actually run in parallel on a parallel computer?
Sometimes it’s hard to know. On a multicore computer, the operating system
might decide to turn off a core to save energy. In a cloud, a computation might
be suspended and moved to a new computer. These are things outside our
control.

www.it-ebooks.info

report erratum • discuss


Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay

×