Reentrant Thoughts

Friday, April 12, 2013

Who is the leader?

Management theorist have dozens of models of leadership, a typical explanation offered as

There are two principal ways to identify the leaders of a group

  1. asking the members to identify which members they regard as most influential in directing the group, or
  2. asking observers to name the most influential members, or to record the frequency of effective influencing actions.

This unfortunately is the general standard of identifying leadership in technology organizations. The two principals, especially the second, appear to be scientific, but are based on the opinions of the members or observers, and their ability to identify effective influencing actions.

Consider the hypothetical scenario of 4 programmer, Arnie, Phyllis, Weber and Martha assigned the task of identifying and fixing a bug in a critical software component. The bug is preventing the deployment of a new version of the software at a customers site with the company losing thousand of dollars each day due to the delay.

All 4 programmers are locked in a room troubleshooting the issue, Arnie, Phyllis and Weber are involved in a discussion determining the best course of action to identify and address the issue. The conversation is as below.

Arnie : We should set up a staging deployment that allows us to isolate the bug in a test scenario to allow us to fix it.

Phyllis : I have attempted this already on a smaller deployment on my developer machine and was not able to identify the root cause.

Weber, looking at Phyllis : Do you think having a subset of the data being used in production would be a better alternative when testing in staging?

Phyllis : May be, however my test cases were fairly exhaustive. I am not confident that obtaining a snapshot of production data will be useful. Moreover taking the snapshot and making it available for testing in staging will delay our fixing the root cause.

Arnie : I agree with Phyllis on the time it will take us to bring in a snapshot of production data. We should approach this situation by taking a two pronged strategy. Phyllis and I will work on setting up the staging environment and creating additional test cases. Weber, please take Martha's assistance to obtaining the snapshot of production data and loading it onto the staging data stores. This will allow us to potentially fix the issue earlier than having production data and no later than tomorrow once we have the data available.

Arnie, Phyllis and Weber are in agreement on the approach.

Arnie looking at Martha, who has her nose buried in a print out for the entire duration of the conversation, asks, "Martha, do you agree with this approach?"

Martha, looking up briefly, nods her head.

Take a minute to evaluate for yourself the leader of the group, rank the 4 people involved in the conversation from a leadership stand point. Who among them had the greatest frequency of "effective influencing actions". If you are like most people you will at this time agree that Arnie was the leader of the group. Most management theorist in the industry will agree on this assessment. Martha's actions were easy to record, she was like a zombie through the entire meeting, studying the printout of the erroneous program. She said nothing, made no gestures and did not even smile or frown.

The conversation continues ...

Arnie : OK, I think we are in agreement, let us meet at 6 PM for a quick status update.
Martha, interrupting Arnie, holding out the print out she was poring over :  I have found the issue, -- pointing to a line of code --, this should be 0x8261A004 not 0x8261A003.

Arnie, Phyllis and Weber resume their animated decision which continues for an additional 30 minutes while they consider test cases from everyone and scenarios that would cause the code to execute. They terminate the meeting, after they had convinced themselves that Martha was indeed correct.

Take a moment, once more the evaluate for yourself who was the most influential and effective leader in the group.

Management theorist, especially those from non technological industries or even those who were mediocre engineers who have transitioned to management and learn about leadership using guidelines like those specified at the beginning, continue in the belief that Arnie is the most influential and leader of the group.

However in terms of solving the problem, the table of effective influencing actions should have read Martha, 1 action, Arnie, Phyllis and Weber, 0 actions.

In summary, Martha clearly had the only "effective influencing action" in terms of solving the problem at hand. However all of Arnie, Phyllis and Weber displayed leadership by not demanding that Martha become an active participant in their discussion, allowing her the freedom to approach the problem in a manner that is most effective for her.

Friday, July 2, 2010

Final modifiers on Method Parameter in Java

Source Gist @ http://gist.github.com/491163
Every so often I run in a Java programmer who uses the final modifier in method parameters in Java. The code usually looks as follows
public void executeOperation(final OperationType ot, final OperationParameters op) {
}
I often wonder whether the programmer has a sufficiently clear understanding of the final modifier when using it is such fashion. Given the JVM call by value semantics, there is only a small benefit associated with the additional typing undertaken to add the final modifier on each method parameter. One question you can expect from someone who has used the final modifier without understanding its implications (or lack of) in the context of method parameters involves overriding such methods and the resolution of the same. This question was recently asked on a mailing list I frequent.

In the following code snippets
public abstract class Base {
public abstract void methodA(final Type xyz);
}

public class Derived extends Base {
public void methodA(Type xyz) {
// .. code
}

// Or when using interfaces
public interface Interface {
public void methodA(final Type xyz);
}

public class Implementation implements Interface {
public void methodA(Type xyz) {
}
}
Why does the compiler not complain, since I am not overriding the method because the signature is not the same.

There are obviously a couple of trivial answers, one of which provided in the mailing list is "Whether or not a method parameter is final isn't one of the considerations taken into account when determining whether or not two methods have override-equivalent signature", accompanied by the obligatory reference to JLS 8.4.2 on Method Signatures. The answer adds to my chagrin, not only is it not a good answer it takes a good learning opportunity and converts it into a rote reference to printed material already available on the internet. This was the answer provided to the question on the mailing list and to my surprise was accepted by the original post.

What then would be a sufficiently good answer? In the remainder of this post I set out my stall and attempt to address the original question. The goal it explain the reason for why the final modifier is not considered part of the method signature.

One reason that I see increasingly more programmers using the final modifier on method parameter is the proliferation of programming languages on the JVM and the increasing extent of the use of multi core processors it is fanciful to try to bring the benefits of immutable state programming from the newer languages to Java. Programmers without a good understanding of any of the languages or the JVM mechanisms use final method modifiers excessively.

Tho, the number of languages on the JVM it is worth recalling the the Java language and the JVM was developed at the same time, and that the JVM was developed primarily for execution of Java sources. As a consequence the JLS specification was constrained by implementation choices on the JVM and vice versa. There was no intention of hosting other languages on the JVM. This situation is currently changing with the upcoming Java 7 release of the language and JVM with support for closures and method handles in the language and the JVM respectively.

What then prevent the JLS to enforce final annotation when resolving overridden method? The JVM obviously, has no knowledge of final modifiers on method parameters, they are just language syntactic sugar. We will demonstrate this using the following code, which uses ASM to perform byte code manipulation. (Explanation of the important snippets follows immediately after)

// FILE: FinalVariableTransformer.java

package c.a;

import static org.objectweb.asm.Opcodes.BIPUSH;
import static org.objectweb.asm.Opcodes.ILOAD;
import static org.objectweb.asm.Opcodes.IMUL;
import static org.objectweb.asm.Opcodes.ISTORE;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;

import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

class InsertInstructionMethodAdapter extends MethodAdapter {
public InsertInstructionMethodAdapter(MethodVisitor mv) {
super(mv);
}

@Override
public void visitVarInsn(int opcode, int var) {

if (opcode == Opcodes.ILOAD && var == 1) {
// MULTIPLY VAR 1 (i) BY 2
mv.visitVarInsn(ILOAD, 1);
mv.visitIntInsn(BIPUSH, 2);
mv.visitInsn(IMUL);
// STORE VAR 1 (i)
mv.visitVarInsn(ISTORE, 1);
}

super.visitVarInsn(opcode, var);
}
}

class InsertInstructionClassAdapter extends ClassAdapter {

public InsertInstructionClassAdapter(ClassVisitor cv) {
super(cv);
}

@Override
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, desc, signature,
exceptions);
if ("timesTen".equals(name))
return new InsertInstructionMethodAdapter(mv);
return mv;
}
}

class InsertInstructionTransformer implements ClassFileTransformer {

@Override
public byte[] transform(ClassLoader loader, String className,
Class classBeingRedefined, ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws IllegalClassFormatException {
return transform(classfileBuffer);
}

public byte[] transform(byte[] classfileBuffer) {
ClassReader cr = new ClassReader(classfileBuffer);
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
ClassAdapter ca = new InsertInstructionClassAdapter(cw);
cr.accept(ca, 0);
return cw.toByteArray();
}

public void transform(String source, String target) throws IOException {
writeFileAsBytes(new File(target), transform(getFileAsBytes(new File(
source))));
}

public void writeFileAsBytes(File file, byte[] bytes) throws IOException {
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(file));
bos.write(bytes);
bos.close();
}

private final byte[] getFileAsBytes(final File file) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
file));
byte[] bytes = new byte[(int) file.length()];
bis.read(bytes);
bis.close();
return bytes;
}
}

public class FinalVariableTransformer {
public static void premain(String agentArguments,
Instrumentation instrumentation) {
instrumentation.addTransformer(new InsertInstructionTransformer());
}

public static void main(String[] args) throws IOException {
if (args.length < 2) {
System.out.println("Require source and target");
return;
}
InsertInstructionTransformer transformer = new InsertInstructionTransformer();
transformer.transform(args[0], args[1]);
}
}

// FILE META-INF/MANIFEST.MF
Manifest-Version: 1.0
Premain-Class: c.a.FinalVariableTransformer

// CLIENT CLASS
public class Simple {
// modify this to be timesTwenty
public int timesTen(final int i) {
return i * 10;
}

public static void main(String[] args) {
Simple s = new Simple();
System.out.println(s.timesTen(2));
}
}

// ON THE COMMAND LINE RUN WITH

java -javaagent:FinalVariableTransformerPackagedAsjar Simple

// AND COMPARE RESULTS WITH JAVAP



That is quite a lot of code, let up take it down in small pieces. The following is the Manifest entry for the premain class when our code is packaged as a jar

// FILE META-INF/MANIFEST.MF
Manifest-Version: 1.0
Premain-Class: c.a.FinalVariableTransformer


The presence of the Premain-Class should indicate to the reader that the class provides a premain method for class instrumentation, using the java.lang.Instrumenation [2] API's. The class FinalVariableTransformer is defined as such

public class FinalVariableTransformer {
public static void premain(String agentArguments,
Instrumentation instrumentation) {
instrumentation.addTransformer(new InsertInstructionTransformer());
}

public static void main(String[] args) throws IOException {
if (args.length < 2) {
System.out.println("Require source and target");
return;
}
InsertInstructionTransformer transformer = new InsertInstructionTransformer();
transformer.transform(args[0], args[1]);
}
}


We implement the method premain with the signature as defined by the API's. We instantiate an instance of InsertInstructionTransformer and add it to the chain of applicable transformations by invoking add on the Instrumentation instance method parameter to premain. InsertInstructionTransformer is defined as below

class InsertInstructionTransformer implements ClassFileTransformer {

@Override
public byte[] transform(ClassLoader loader, String className,
Class classBeingRedefined, ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws IllegalClassFormatException {
return transform(classfileBuffer);
}

public byte[] transform(byte[] classfileBuffer) {
ClassReader cr = new ClassReader(classfileBuffer);
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
ClassAdapter ca = new InsertInstructionClassAdapter(cw);
cr.accept(ca, 0);
return cw.toByteArray();
}

public void transform(String source, String target) throws IOException {
writeFileAsBytes(new File(target), transform(getFileAsBytes(new File(
source))));
}

public void writeFileAsBytes(File file, byte[] bytes) throws IOException {
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(file));
bos.write(bytes);
bos.close();
}

private final byte[] getFileAsBytes(final File file) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
file));
byte[] bytes = new byte[(int) file.length()];
bis.read(bytes);
bis.close();
return bytes;
}
}


InsertInstructionTransformer implements the interface ClassFileTransformer and provides an implementation of the transform method. While the class InsertInstructionTransformer has methods to obtain the bytes associated with a class, we are mostly interested in the following method

public byte[] transform(byte[] classfileBuffer) {
ClassReader cr = new ClassReader(classfileBuffer);
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
ClassAdapter ca = new InsertInstructionClassAdapter(cw);
cr.accept(ca, 0);
return cw.toByteArray();
}


Given a class file as a byte array, we instance an instance of ClassReader which is part of the ASM byte code manipulation library. The ASM library provide easy mechanism for byte code manipulation. The API provide 2 ways to access class byte code, one uses a Tree API and the other a Visitor design pattern. The following code uses the Visitor design pattern. Of interest to us is the implementation of InsertInstructionClassAdapter

class InsertInstructionClassAdapter extends ClassAdapter {

public InsertInstructionClassAdapter(ClassVisitor cv) {
super(cv);
}

@Override
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, desc, signature,
exceptions);
if ("timesTen".equals(name))
return new InsertInstructionMethodAdapter(mv);
return mv;
}
}


InsertInstructionClassAdapter extends ClassAdapter and makes use of the method visitor return by the super implementation. The default implementation of Visitor interfaces in ASM do not provide for any manipulation, that is out responsibility. We wish to change the byte code of any method with the name
timesTen
and return the method visitor implementation InsertInstructionMethodAdapter when a method with this name is encountered.

Let us examine the class InsertInstructionMethodAdapter, reproduced below

class InsertInstructionMethodAdapter extends MethodAdapter {
public InsertInstructionMethodAdapter(MethodVisitor mv) {
super(mv);
}

@Override
public void visitVarInsn(int opcode, int var) {

if (opcode == Opcodes.ILOAD && var == 1) {
// MULTIPLY VAR 1 (i) BY 2
mv.visitVarInsn(ILOAD, 1);
mv.visitIntInsn(BIPUSH, 2);
mv.visitInsn(IMUL);
// STORE VAR 1 (i)
mv.visitVarInsn(ISTORE, 1);
}

super.visitVarInsn(opcode, var);
}
}


While the MethodVisitor provides for many methods to be overridden we override just the
visitVarInsn
method. On the occurrence of a load Opcode with for the first method parameter we insert the following opcodes prior to passing in the original opcode the the parent method adapter.

// MULTIPLY VAR 1 (i) BY 2
mv.visitVarInsn(ILOAD, 1);
mv.visitIntInsn(BIPUSH, 2);
mv.visitInsn(IMUL);
// STORE VAR 1 (i)
mv.visitVarInsn(ISTORE, 1);


We load the first method parameter, push the constant 2 on to the stack, multiply the first 2 elements on the stack and store the result to the method parameter value. Looking at our Simple class, reproduced below

// CLIENT CLASS
public class Simple {
// modify this to be timesTwenty
public int timesTen(final int i) {
return i * 10;
}

public static void main(String[] args) {
Simple s = new Simple();
System.out.println(s.timesTen(2));
}
}


It is the equivalent of performing the following source code transformation

// CLIENT CLASS
public class Simple {
// modify this to be timesTwenty
public int timesTen(final int i) {
i *= 2;
return i * 10;
}

public static void main(String[] args) {
Simple s = new Simple();
System.out.println(s.timesTen(2));
}
}


Clearly this not something that the Java compiler would permit you to do, however running the code passes it through the byte code verifier that is part of the JVM and executes successfully with the result of multiplication by 20 rather than 10. Or put another way the JVM does not understand finality with reference to method parameters. Which begs the question, but why.

As any Java programmer would tell in java you maintain and pass around reference to object. Most will also tell you that Java (by extension the JVM) supports only call by value. Often not understood and lost in the trivial statement of fact is how the references interact when passed by value. It is the value of the reference that is passed to the invoked method, take a moment to read that again, value of the reference. Any changes to the value does not impact the original reference, only changes to the referenced object are visible outside of the method when it returns. Or, the JVM has no use for enforcing of method parameter finality.


[1] http://java.sun.com/docs/books/jls/third_edition/html/classes.html#38649
[2] http://java.sun.com/j2se/1.5.0/docs/api/java/lang/instrument/package-summary.html?PHPSESSID=99d1bf24adfefafb49c6f143c76dc59e

Sunday, March 28, 2010

Resumes are ridiculous but so are cover letters

37Signals as a company is an Outlier, successful from a number of measures and with limited success if viewed from a different perspective.

Their recent book Rework shines a light on ideas and practices that makes them successful at what they do. 37Signals as a company considers themselves to be successful, however with few ideas on how to scale their ideas. Measuring success unfortunately is based on the scale that you operate. Is 37Signals as successful as Apple? No. Will they ever be as successful as Apple? No. Do they care? No. While comparing most companies with Apple would make the company look unsuccessful, the measure of success is relative to your reference. Pick a company X that is substantially less successful than Apple and compare it with 37Signals, how does company X fare? Or 37Signals? On what measure of success do you compare? How does Apple from 10 yrs back compare to 37Signals.

Human beings are inclined to be certain, certainty is a mental state, not unlike anger or pride it can help guide you but does not dependably reflect objective truth. If you make the mistake of emphasizing you certainty it provides a positive feedback loop making you entirely more certain on being certain. This invariably results in downfall, you are fooled by randomness, and fail to grasp the significance of the hidden role of chance in you success. Outwardly 37Signals as a company comes off as being certain (this may not be true once you are in the fold), but you should be aware of the positive reinforcement of being certain. Read Rework if you have to but do not use its pontification to validate your strategy. Test and retest your ideas often, be uncertain. You might find that previously successful ideas not longer work and vice verse.

I have not read Rework, do not intend to. The book resonates with some entrepreneurs. On the strategy of hiring the book says the following
  1. Resumes are ridiculous
    “You want a specific candidate who cares specifically about your company, your products, your customers, and your job… Check their cover letter … you hear someone’s actual voice and are able to recognize if it’s in tune with you and your company. Trust your gut reaction.”
"Check their cover letter" are you kidding me, what bull. I certainly agree with the idea that resumes are ridiculous, however cover letters are an extension of the resume, written by the same individual, for the same purpose. They are just as ridiculous.

You certainly want a candidate who cares about your company, your products and your customers. However care comes with trust, and trust is developed over a period of time, like in any symbiotic relationship. If you are true to yourself, look only for a candidate who cares about the job. Resumes, cover letters and what a candidate says (to be in tune with you and your company) only indicate that the candidate cares about the paycheck and benefits you might offer. Determine if the candidate cares about the job and he/she will eventually care about your company, product and customer.

For a position in programming (which is what I am most familiar with and competent to speak about) it is fairly easy to determine if the candidate cares about the job. To care about the job the candidate needs to care about programming and in the age of the internet it is fairly easy to demonstrate.

Do your research on the candidate, it is not just about knowing algorithms and the ability to apply those to problem solving it is also about what you have done with the ability in the past. A lot of companies hire candidates based on past performance. Do not look too far into the past, the immediate past is significantly better indicator of success. It does not matter that the candidate has graduated from a top tier school if it was 5 yrs in the past as it matters if the candidate contributes to open source projects? It does not matter if the candidate is a top performer during the past 5 yrs in his current position, if he/she desires to leave current employment determine why. If the candidate is leaving in spite of caring about the current company, product and customer, (on which you have to take the candidates word for), determine only if the candidate cares about the job. It is your best indicator of success.

As a corollary, never hire someone who does not care about the job. But, you would never do that would you, irrespective of what their resume or cover letter says, would you?

Am I being certain?

Saturday, March 27, 2010

On why double checked locking is an anti-pattern

If you are a Java programmer by now you are probably aware of the double checked locking concurrency anti-pattern.
public final class ResourceAccessor {
private static Resource r;

public static Resource getResource(){
if(r == null) {
synchronized(ResourceAccessor.class){
if(r == null) {
r = new Resource();
}
}
}
return r;
}
}

There are several variation of double check locking code style, but the important lines of code are 5 and 7. The check for resource before obtaining a lock on line 5 and a second check on line 7.

This fancy trick employed specifically in early version of Java to optimize code to avoid (then) expensive lock operations has been found to be wrong. Often the best explanations will tell you that "a second thread may see a partially constructed resource object".

You might also find the following alternative of a correct implementation
public final class ResourceAccessor {
private static volatile Resource r;

public static Resource getResource(){
if(r == null) {
synchronized(ResourceAccessor.class){
if(r == null) {
r = new Resource();
}
}
}
return r;
}
}
The reason for both the correct and incorrect behavior are rooted in the Java Memory Model, which can be found at Chapter 17 of the Java Language Specification.

Unfortunately most explanation stop there, along with, on occasion a reference to the "happens before" ordering referenced by the Java Memory Model.

We will dig a little deeper to try to better understand the reason for why double checked locking is incorrect and also look at why using a volatile reference to the variable fixes it.

Abstractions while necessary to hide complexity in large systems also prevent us from gaining a better understanding the behavior of the systems. We will use java byte code in an attempt to help us understand the reasons, it serves our purpose in this instance, however be aware that byte code is only an abstraction.

Java does not enforce a full execution order on code, it provides only a partial ordering defined in Chapter 17 of the language specification as happens-before. Quite simply it mean the results of a write by one thread are guaranteed to be visible to a read by another thread only if the write operation happens-before the read operation. Intuitively this is correct, however how does a programmer enforce a happens-before ordering in code.

Happens-before ordering can be enforced using one of the synchronization mechanism provided by Java
  • Locks, either intrinsic locking using synchronized or using locks from java.util.concurrent which have the same semantics as intrinsic locking
  • volatile, reads and write to volatile variables are atomic.
  • Thread.start() and Thread.join() method invocation
A more refined version of happen-before ordering is defined in the package javadoc for java.util.concurrent as follows
  • Each action in a thread happens-before every action in that thread that comes later in the program's order.
  • An unlock (synchronized block or method exit) of a monitor happens-before every subsequent lock (synchronized block or method entry) of that same monitor. And because the happens-before relation is transitive, all actions of a thread prior to unlocking happen-before all actions subsequent to any thread locking that monitor.
  • A write to a volatile field happens-before every subsequent read of that same field. Writes and reads of volatile fields have similar memory consistency effects as entering and exiting monitors, but do not entail mutual exclusion locking.
  • A call to start on a thread happens-before any action in the started thread.
  • All actions in a thread happen-before any other thread successfully returns from a join on that thread.

Taking a closer look at the original double checked locking code (reproduced here)
public final class ResourceAccessor {
private static Resource r;

public static Resource getResource(){
if(r == null) {
synchronized(ResourceAccessor.class){
if(r == null) {
r = new Resource();
}
}
}
return r;
}
}
It would seems that the rule
  • Each action in a thread happens-before every action in that thread that comes later in the program's order.
would require that we see only references to resource r that are fully constructed. Since the program order requires that a new Resource() be created before being assigned to variable r.

As mentioned previously the Java language is an abstraction over the byte code specification, and what seems like 2 statements from the Java language perspective is anything but

The single statement translates to the following byte code

18: new #4; //class ResourceAccessor$Resource
21: dup
22: aconst_null
23: invokespecial #5; //Method ResourceAccessor$Resource."

":(LResourceAccessor$1;)V
26: putstatic #2; //Field r:LResourceAccessor$Resource;

Line 18 allocates memory
Line 23 invokes the constructor
Line 26 sets the reference to field r

It is possible that the reference to field r be set prior to execution of the constructor (change execution order of lines 23 and 26) all along staying within the constraints enforced by happens-before. In fact there is at least one example of such an occurrence.

The reason that the following code
public final class ResourceAccessor {
private static volatile Resource r;

public static Resource getResource(){
if(r == null) {
synchronized(ResourceAccessor.class){
if(r == null) {
r = new Resource();
}
}
}
return r;
}
}
executes correctly is because of the rule
  • A write to a volatile field happens-before every subsequent read of that same field. Writes and reads of volatile fields have similar memory consistency effects as entering and exiting monitors, but do not entail mutual exclusion locking.
which requires that the thread attempting to read variable r block until such time as resource referenced by r is not fully constructed.