Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesModelSurrogate.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesModelSurrogate.cs	(revision 14235)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesModelSurrogate.cs	(revision 14236)
@@ -57,5 +57,9 @@
 
     public override IEnumerable<string> VariablesUsedForPrediction {
-      get { return actualModel.Models.SelectMany(x => x.VariablesUsedForPrediction).Distinct().OrderBy(x => x); }
+      get
+      {
+        lock (actualModel) { if (actualModel == null) actualModel = RecalculateModel(); }
+        return actualModel.Models.SelectMany(x => x.VariablesUsedForPrediction).Distinct().OrderBy(x => x);
+      }
     }
 
@@ -105,5 +109,5 @@
     // forward message to actual model (recalculate model first if necessary)
     public override IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
-      if (actualModel == null) actualModel = RecalculateModel();
+      lock (actualModel) { if (actualModel == null) actualModel = RecalculateModel(); }
       return actualModel.GetEstimatedValues(dataset, rows);
     }
@@ -119,5 +123,5 @@
     public IEnumerable<IRegressionModel> Models {
       get {
-        if (actualModel == null) actualModel = RecalculateModel();
+        lock(actualModel) { if (actualModel == null) actualModel = RecalculateModel();}
         return actualModel.Models;
       }
@@ -126,5 +130,5 @@
     public IEnumerable<double> Weights {
       get {
-        if (actualModel == null) actualModel = RecalculateModel();
+        lock(actualModel) { if (actualModel == null) actualModel = RecalculateModel();}
         return actualModel.Weights;
       }
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/NearestNeighbour/NearestNeighbourModel.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/NearestNeighbour/NearestNeighbourModel.cs	(revision 14235)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/NearestNeighbour/NearestNeighbourModel.cs	(revision 14236)
@@ -200,11 +200,14 @@
           x[column] = inputData[row, column];
         }
-        int actNeighbours = alglib.nearestneighbor.kdtreequeryknn(kdTree, x, k, false);
-        alglib.nearestneighbor.kdtreequeryresultsdistances(kdTree, ref dists);
-        alglib.nearestneighbor.kdtreequeryresultsxy(kdTree, ref neighbours); // gkronber: this call changes the kdTree data structure
+        int numNeighbours;
+        lock (kdTree) { // gkronber: the following calls change the kdTree data structure
+          numNeighbours = alglib.nearestneighbor.kdtreequeryknn(kdTree, x, k, false);
+          alglib.nearestneighbor.kdtreequeryresultsdistances(kdTree, ref dists);
+          alglib.nearestneighbor.kdtreequeryresultsxy(kdTree, ref neighbours);
+        }
 
         double distanceWeightedValue = 0.0;
         double distsSum = 0.0;
-        for (int i = 0; i < actNeighbours; i++) {
+        for (int i = 0; i < numNeighbours; i++) {
           distanceWeightedValue += neighbours[i, columns] / dists[i];
           distsSum += 1.0 / dists[i];
@@ -233,10 +236,13 @@
           x[column] = inputData[row, column];
         }
-        int actNeighbours = alglib.nearestneighbor.kdtreequeryknn(kdTree, x, k, false);
-        alglib.nearestneighbor.kdtreequeryresultsdistances(kdTree, ref dists);
-        alglib.nearestneighbor.kdtreequeryresultsxy(kdTree, ref neighbours);
-
+        int numNeighbours;
+        lock (kdTree) {
+          // gkronber: the following calls change the kdTree data structure
+          numNeighbours = alglib.nearestneighbor.kdtreequeryknn(kdTree, x, k, false);
+          alglib.nearestneighbor.kdtreequeryresultsdistances(kdTree, ref dists);
+          alglib.nearestneighbor.kdtreequeryresultsxy(kdTree, ref neighbours);
+        }
         Array.Clear(y, 0, y.Length);
-        for (int i = 0; i < actNeighbours; i++) {
+        for (int i = 0; i < numNeighbours; i++) {
           int classValue = (int)Math.Round(neighbours[i, columns]);
           y[classValue]++;
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationModel.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationModel.cs	(revision 14235)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationModel.cs	(revision 14236)
@@ -22,4 +22,8 @@
 using System.Collections.Generic;
 namespace HeuristicLab.Problems.DataAnalysis {
+  /// <summary>
+  /// Interface for all classification models.
+  /// <remarks>All methods and properties in in this interface must be implemented thread safely</remarks>
+  /// </summary>
   public interface IClassificationModel : IDataAnalysisModel {
     IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows);
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataAnalysisModel.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataAnalysisModel.cs	(revision 14235)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataAnalysisModel.cs	(revision 14236)
@@ -24,4 +24,8 @@
 
 namespace HeuristicLab.Problems.DataAnalysis {
+  /// <summary>
+  /// Interface for all data-analysis models (regression/classification/clustering).
+  /// <remarks>All methods and properties in in this interface must be implemented thread safely</remarks>
+  /// </summary>
   public interface IDataAnalysisModel : INamedItem {
     IEnumerable<string> VariablesUsedForPrediction { get; }
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionModel.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionModel.cs	(revision 14235)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionModel.cs	(revision 14236)
@@ -23,4 +23,8 @@
 
 namespace HeuristicLab.Problems.DataAnalysis {
+  /// <summary>
+  /// Interface for all regression models.
+  /// <remarks>All methods and properties in in this interface must be implemented thread safely</remarks>
+  /// </summary>
   public interface IRegressionModel : IDataAnalysisModel {
     IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows);
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/TimeSeriesPrognosis/ITimeSeriesPrognosisModel.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/TimeSeriesPrognosis/ITimeSeriesPrognosisModel.cs	(revision 14235)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/TimeSeriesPrognosis/ITimeSeriesPrognosisModel.cs	(revision 14236)
@@ -22,4 +22,8 @@
 using System.Collections.Generic;
 namespace HeuristicLab.Problems.DataAnalysis {
+  /// <summary>
+  /// Interface for all time series prognosis models.
+  /// <remarks>All methods and properties in in this interface must be implemented thread safely</remarks>
+  /// </summary> 
   public interface ITimeSeriesPrognosisModel : IRegressionModel {
     IEnumerable<IEnumerable<double>> GetPrognosedValues(IDataset dataset, IEnumerable<int> rows, IEnumerable<int> horizons);
