Final Review B: Questions
One of the downsides to locking-based systems is priority inversion. Explain what this is.
What is an advantage of using Java's ConcurrentHashMap
class (from java.util.concurrent
) rather than using a
simple HashMap
with a lock obtained for each access
(such as would be constructed with
Collections.synchronizedMap(new HashMap())
)?
Explain the function of the semicolon operator in ALGOL 68.
What happens with the statement
“INT a = (print(3); 5)
”?
Aside from declaring two different names, how are the following two ALGOL 68 variable declarations different?
INT first sym = 3;
REF INT second sym = LOC INT := 3;
In D, what is a pure function?
What is displayed by the following D code? And what would be displayed if the word lazy were omitted?
void repeat(int n, lazy int val) {
for (int i = 0; i < n; i++) {
writeln(val);
}
}
void main() {
int x = 1;
repeat(3, x *= 2);
}
What distinguishes functions and operators in APL? Give an example of each.
Write an APL expression that computes the 100th harmonic number — i.e., 1/1 + 1/2 + 1/3 + ... + 1/100. Recall that APL's ‘ι’ function takes an integer n and produces a vector of integers from 0 to n − 1.
Final Review B: Solutions
In systems where threads can be given different priorities, locking can undermine the priority system whenever a high-priority thread desires a lock held by a low-priority thread: Either the system must temporarily grant the low-priority thread a high priority so that it can finish its work with the lock, or else the high-priority thread will be stalled while the low-priority thread completes its work.
Both prevent conflicts between threads
attempting simultaneously accessing the HashMap
.
However, the single-lock HashMap
will lead to reduce
performance, since it will permit only one thread at a time to
access the HashMap
, whereas a ConcurrentHashMap
will allow simultaneously access when the requests don't
conflict (such as when the requests map to different buckets of
the hash table).
This is the go-on operator: Given “A; B”, the value of A is computed before B, and the overall value of the expression is the value of B.
For instance, the
expression “print(3); 5
” represents
first computing the value of print(3)
then the value of 5,
and the overall result is 5.
The declaration of first sym
creates a constant:
first sym
cannot later be changed.
By contrast, second sym
is a variable whose value can
later be changed with a statement such as “second sym := 4
”.
A pure function is one that basically has no side effects: It does not perform I/O, access any memory beyond its own local memory and what is accessible through its arguments, or call non-pure functions.
2
4
8
Without lazy, this program would print 2 three times.
A function operates on numeric vectors as parameters and produces a numeric vector as a result, whereas an operator operates on functions as parameters and produces a function as a result. Examples of function include ‘÷’ for division and ‘↓’ for dropping items from a vector; examples of operators include ‘/’ for folding/reducing a function (for example, ‘+/’ creates a function that will sum the values of an vector) or ‘¨’ to apply a function to each item of a vector.
+/÷1+ι100