code: private void doGenerateBrownianMotion() {
  		if(brownianIncrements != null)
  		{
  			return;	// Nothing to do
  		}
  
  		BrownianMotion generator = new BrownianMotion(timeDiscretization, numberOfFactors, numberOfPaths, seed);
  
  		// Allocate memory
  		brownianIncrements = new RandomVariableInterface[generator.getTimeDiscretization().getNumberOfTimeSteps()][generator.getNumberOfFactors()];
  
  		double endTime 		= getTimeDiscretization().getTime(getTimeDiscretization().getNumberOfTimeSteps());
  		for(int factor=0; factor<generator.getNumberOfFactors(); factor++) {
  			// The end point
  			RandomVariableInterface endOfFactor		= end[factor];
  			// Initialized the bridge to the start point
  			RandomVariableInterface brownianBridge	= start[factor];
  			for(int timeIndex=0; timeIndex<getTimeDiscretization().getNumberOfTimeSteps(); timeIndex++) {
  				double currentTime	= getTimeDiscretization().getTime(timeIndex);
  				double nextTime		= getTimeDiscretization().getTime(timeIndex+1);
  				double alpha		= (nextTime-currentTime)/(endTime-currentTime);
  
  				// Calculate the next point using the "scheme" of the Brownian bridge
  				RandomVariableInterface nextRealization = brownianBridge.mult(1.0-alpha).add(endOfFactor.mult(alpha)).add(generator.getBrownianIncrement(timeIndex, factor).mult(Math.sqrt(1-alpha)));
  
  				// Store the increment
  				brownianIncrements[timeIndex][factor] = nextRealization.sub(brownianBridge);
  
  				// Update the bridge to the current point
  				brownianBridge = nextRealization;
  			}
  		}
  	}
docs: Lazy initialization of brownianIncrement. Synchronized to ensure thread safety of lazy init.