diff --git a/python/dune/perftool/sumfact/autotune.py b/python/dune/perftool/sumfact/autotune.py
index 771b792af98bb68d8fbdafc8c2ae6a05b61fb7e7..2cdd2e089f4299c650a25ffa86cf94bbd6112935 100644
--- a/python/dune/perftool/sumfact/autotune.py
+++ b/python/dune/perftool/sumfact/autotune.py
@@ -11,6 +11,7 @@ from pytools import product
 import os
 import re
 import subprocess
+import filelock
 
 
 def get_cmake_cache_entry(entry):
@@ -193,28 +194,29 @@ def autotune_realization(sf):
     name = os.path.join(dir, "autotune_sumfact_{}".format(sf.function_name))
     filename = os.path.join(dir, "{}.cc".format(basename))
     logname = os.path.join(dir, "{}.log".format(basename))
-
-    # If the log file already exists, we can reuse the benchmark results
-    # and do not need to rerun it.
-    if not os.path.isfile(logname):
-        # Generate and compile a benchmark program
-        with cache_restoring():
-            generate_standalone_code(sf, filename, logname)
-
-        ret = subprocess.call(compiler_invocation(name, filename))
-        assert ret == 0
-
-        # Check whether the user specified an execution wrapper
-        call = []
-        wrapper = get_cmake_cache_entry("DUNE_PERFTOOL_BENCHMARK_WRAPPER")
-        if wrapper:
-            call.append(wrapper)
-
-        # Run the benchmark program
-        call.append(name)
-        devnull = open(os.devnull, 'w')
-        ret = subprocess.call(call, stdout=devnull, stderr=subprocess.STDOUT)
-        assert ret == 0
+    lock = "{}.lock".format(name)
+
+    # Generate and compile a benchmark program
+    with cache_restoring():
+        with filelock.FileLock(lock):
+            if not os.path.isfile(logname):
+                if os.path.isfile(filename):
+                    generate_standalone_code(sf, filename, logname)
+
+                ret = subprocess.call(compiler_invocation(name, filename))
+                assert ret == 0
+
+                # Check whether the user specified an execution wrapper
+                call = []
+                wrapper = get_cmake_cache_entry("DUNE_PERFTOOL_BENCHMARK_WRAPPER")
+                if wrapper:
+                    call.append(wrapper)
+
+                # Run the benchmark program
+                call.append(name)
+                devnull = open(os.devnull, 'w')
+                ret = subprocess.call(call, stdout=devnull, stderr=subprocess.STDOUT)
+                assert ret == 0
 
     # Extract the result form the log file
     return float(next(iter(open(logname, "r")))) / 1000000
diff --git a/python/setup.py b/python/setup.py
index 476a9f6f7b5399c04837af8eb5e627f4182156f2..e4517d2f7f6c1b57b7f57f69c90b20a5f4a05f3f 100644
--- a/python/setup.py
+++ b/python/setup.py
@@ -41,7 +41,7 @@ setup(name='dune.perftool',
                 'dune.perftool.ufl',
                 'dune.perftool.ufl.transformations',
                 ],
-      install_requires=['dune.testtools', 'sympy', 'frozendict', 'pytest', 'pytest-pep8'],
+      install_requires=['dune.testtools', 'sympy', 'frozendict', 'pytest', 'pytest-pep8', 'filelock'],
       cmdclass={'test': PyTest},
       entry_points = {
         "console_scripts": [