Presentation is loading. Please wait.

Presentation is loading. Please wait.

© 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 1 Concurrency in Programming Languages Matthew J. Sottile Timothy G. Mattson Craig.

Similar presentations


Presentation on theme: "© 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 1 Concurrency in Programming Languages Matthew J. Sottile Timothy G. Mattson Craig."— Presentation transcript:

1 © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 1 Concurrency in Programming Languages Matthew J. Sottile Timothy G. Mattson Craig E Rasmussen

2 © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 2 Chapter 5 Objectives Examine high-level language constructs and how concurrency impacts them. Introduce the cognitive dimensions framework for evaluating language features.

3 Outline Familiar language constructs Evaluating language constructs Interactions with concurrency © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 3

4 Language constructs What is a “language construct”? These are the building blocks that languages provide programmers to put programs together. Examples: –loop operators (for, while, do) –conditionals (if/then/else, switch, case) –arithmetic operations –types –data structures (arrays, records, containers) © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 4

5 Purpose The purpose of these constructs is to raise the abstraction level that programmers work at. The compiler for a language is responsible for converting these down to a lower level machine representation. –Or virtual machine representation, which is becoming commonplace in environments like Java and.NET. © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 5

6 Abstraction layers © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 6

7 Expressions Expressions represent computations on variables. Typically they are composed of unary and binary operations on data objects. They provide a way to concisely describe complex computations, instead of requiring the programmer to decompose them into the sequence of actual operations required to implement them. © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 7

8 Example expression Equations like the one below appear all the time in code for financial applications, games, simulations, graphics, etc… Expressions are used to represent this in code: © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 8 sum += pow(a+i,3.0) * (i * b + (c/d));

9 Example expression That simple expression will likely be implemented with much more verbose, low level operations: Expressions support this abstraction over the verbose sequence of little operations. © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 9 tmp = c/d; tmp2 = i*b; tmp = tmp + tmp2; tmp2 = a+i; tmp3 = a+i; tmp2 = tmp2 * tmp2; tmp2 = tmp2 * tmp3; tmp = tmp * tmp2; sum = sum + tmp; sum += pow(a+i,3.0) * (i * b + (c/d));

10 Expressions and concurrency Expressions are turned into sequences of smaller operations. As a result, evaluating an expression may itself not be an atomic operation. If an expression references a location in memory that is shared with other threads of execution, there is potential for conflicts. © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 10

11 Example This expression references the value at a[1] twice. If the compiler doesn’t emit code that atomically reads and caches the value stored there, then the thread executing the expression may read the location at two different times. The result could be impacted by another thread updating the location between reads. © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 11 x = a[1] + (a[0] * (b[1] / a[1]))

12 Side-effects Side-effects are a common source of complication for concurrent programming. In the last example, the fact that the expression directly references memory that another thread can modify means that threads can cause effects visible to other threads. An operation that changes the state of the world (either memory or IO) can be said to have side- effects. © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 12

13 Side-effects Code that performs only computations with no side effects is often called “pure”. Impure code does more than compute – it has a tangible effect on the world. Functional languages often devote more attention to purity than other language families. –For example, in Haskell side effects are explicitly indicated by the type that a computation has. © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 13

14 Side-effects Why do side effects complicate concurrency? Effects make the result of a program highly dependent on the order by which program statements are executed across interacting threads. The less dependencies that exist between statements, the more flexibility that the compiler or programmer have to exploit concurrency. –Side-effects induce dependencies between threads. © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 14

15 Control flow primitives Expressions define computations, while control flow primitives help control the sequences of computations occur. Loops are a common example – instead of enumerating all repetitions of a block of code, the loop represents one copy and an expression representing how many times to repeat it. –Some loops, like for loops, also provide parameters for each iteration of the loop body. © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 15

16 Control flow primitives Conditionals are another example: –Simple branching via if-then-else –More general branching via switch or case statements. Control flow primitives can reveal potential concurrency in a program. Loops are the most common control flow primitive that reveals concurrency. © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 16

17 Loops A loop repeats a sequence of statements. In some cases, the Nth iteration uses the results of the (N-1)th iteration. –This means that there is a dependency between loop iterations. Order matters. In other cases though, the loop iterations are either entirely or partially independent. –Independence indicates that order of execution of the loop iterations isn’t important. © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 17

18 Example Say we have a loop that runs through the rows in a 2D image, and performs a computation on each row that has no dependency on the state of any of the other rows. –Each row could be processed concurrently with the others. Dependence analysis of loops can get tricky when loops are nested. Dependencies may exist between outer loops, but not within inner loops. –Concurrency exists, but with limitations. © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 18

19 Abstract types and data structures Languages also provide abstractions over the way data is represented in the machine. –Different types of numbers, strings, and structured types like records and objects. This is a big convenience both for managing memory and hiding data representations (e.g., how a complex number is stored). Data structures interact with concurrent code in interesting ways. © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 19

20 Data structures Primitive types that are updated atomically at the machine level have few issues with concurrency since atomicity is guaranteed by hardware. Other types though do not have this hardware protection. –Arrays –Record types (e.g., C structs) –Objects © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 20

21 Data structures As we saw earlier in discussing monitors, there are mechanisms to protect complex data structures from concurrency bugs. Languages like Java provide language features like the synchronized keyword to protect data structures. Programmers frequently use explicit locks to protect data structures that are not protected at the language level. © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 21

22 Functions and subroutines Finally, languages provide constructs for holding blocks of code. –Often to support parameterized reuse. –Functions often can be used to define the body of concurrently executing threads. Some languages allow functions to have types that indicate whether or not the function has side- effects. –This helps compilers and programmers reason about functions in concurrent environments. © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 22

23 Outline Familiar language constructs Evaluating language constructs Interactions with concurrency © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 23

24 Evaluating language constructs A challenge for selecting language constructs, especially those that relate to concurrent programming, is selecting ones that make programming easier. Three criteria can be used to evaluate language constructs as proposed by Sebesta: –Readability –Writeability –Reliability © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 24

25 Readability A program really is a form of communication to: –The compiler, to generate a program that does what we want it to do. –Other programmers, who may need to work on the code independently. –Ourselves, since we often can’t keep all of the program logic in our heads for huge programs developed over long periods of time. Good language constructs make programs easy to read and understand the meaning of. © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 25

26 Writeability Very closely tied to readability. A language should make it easy to express the logic of the problem being solved in code. © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 26

27 Reliability Language constructs should have a well defined behavior in all situations. Type systems, error and exception handling systems all help towards this end. Features that ensure reliability can come at a cost of writeability by making code more verbose. –Example: requiring explicit type signatures instead of relying on dynamic runtime type checking. © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 27

28 Cognitive dimensions Sebesta’s criteria are useful, but miss nuances that are very important in evaluating how language features are used by programmers. Green proposed a set of ‘cognitive dimensions’ that can be used to evaluate language constructs. These dimensions are very interesting with respect to concurrent programming. © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 28

29 Cognitive Dimensions Viscosity: How much work is required to make a change? A language that has high viscosity resists changes by making it difficult to make them. –Example: having to edit many parts of the source code to rename a function. Visibility: How easily can the programmer see parts of the system? Data encapsulation methods can hinder visibility while enhancing protection. –Example: Hiding data in a monitor can increase robustness in concurrent setting, but can limit fine- grained performance tuning. © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 29

30 Cognitive Dimensions Premature commitment: Forcing the programmer to make decisions before they have sufficient information to make them. Committing to a memory layout before knowing the number of threads that will share it is an example. Hidden dependencies: A language construct that is dependent on another without being explicitly stated is an example of this. This can occur in object hierarchies in which derived classes depend implicitly on a hidden property of a parent class. © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 30

31 Cognitive Dimensions Role-expressiveness: This measures how clearly the role of an entity is in the code that uses it. –Example: an explicit semaphore type makes the role of a semaphore variable clearer than an integer used for the same purpose. Error proneness: Error prone constructs invite mistakes and rarely protect from them. –Example: C pointers are error prone. Java object references serve a similar purpose, but are less error prone since a well defined exception will be thrown that can be caught and dealt with. © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 31

32 Cognitive Dimensions Abstraction: Abstractions make key features of a system explicit, while hiding less essential features. A language that encourages abstraction can be called abstraction rich, while languages that discourage it are abstraction poor. –Languages that force excessive use of abstractions can be challenging to use, and present programmers with an abstraction barrier. © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 32

33 Cognitive Dimensions These are presented here to define a rigorous methodology that can be used when faced with a choice between languages. –Cognitive dimensions provide a concrete set of criteria for evaluating languages and their features. Given the explosion of languages with concurrency features over the last decade, this framework is valuable for making sense of how languages may compare with each other with an emphasis on programmer productivity. © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 33

34 Outline Familiar language constructs Evaluating language constructs Interactions with concurrency © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 34

35 Implications of concurrency Languages are hard to design, even in sequential settings. Designers often seek what is known as orthogonality in their choice of language features. –Orthogonality means that the different features don’t interact with each other in unexpected or difficult ways. For example, the meaning of the while-loop language construct isn’t changed by the contents of the loop body in unexpected ways. While-loops are always while-loops. © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 35

36 Implications of concurrency Concurrency often violates orthogonality goals. Example: A variable shared by multiple threads can lead to race conditions in assignment statements. –Different results depending on concurrent interactions. This makes assignment operators dependent on threading operations, violating traditional orthogonality assumptions. © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 36

37 Implications of Concurrency Languages that integrate concurrency at the language level are far more likely to provide assurances of orthogonality between concurrency control primitives and other parts of the language. –Examples: Explicit guarantees of atomicity of expressions or statements Language-level blocking semantics for shared or locked data, where blocking behavior is part of the language instead of forced to be handled by the programmer. Most new languages are taking concurrency into account, as are revised standards for older ones. © 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 37


Download ppt "© 2009 Matthew J. Sottile, Timothy G. Mattson, and Craig E Rasmussen 1 Concurrency in Programming Languages Matthew J. Sottile Timothy G. Mattson Craig."

Similar presentations


Ads by Google