diff --git a/dune/xt/common/parallel/threadstorage.hh b/dune/xt/common/parallel/threadstorage.hh
index 00eb9ddb21acc1b46672ed7d41488043f2fbaa0f..f1e3c2c196df1c732931847085310666aa97b79b 100644
--- a/dune/xt/common/parallel/threadstorage.hh
+++ b/dune/xt/common/parallel/threadstorage.hh
@@ -256,6 +256,118 @@ private:
 }; // class PerThreadValue<ValueImp>
 
 
+/**
+ * Previous implementation of PerThreadValue. This implementation suffers from the fact that it is not possible (or
+ * at least we did not find a way yet) to set a hard upper limit on the number of threads TBB uses. Setting max_threads
+ * via tbb::task_scheduler_init apparently only sets a soft limit on the number of threads. In addition, even if TBB
+ * uses only N threads at a time, it might be possible that a thread is destroyed and later in the program another
+ * thread with a different id replaces it, which will then get a number greater than or equal to N in our
+ * implementation (see ThreadManager::thread()). This occasionally leads to segfaults.
+ * We keep this implementation around as it is currently used by TimingData (see dune/xt/common/timings.hh) and the
+ * new implementation can't replace it in that context, as the new implementation based on
+ * tbb::enumerable_thread_specific lazily initalizes the values in each thread.
+ * \todo Either fix TimingData and remove this class or fix this class.
+ **/
+template <class ValueImp>
+class UnsafePerThreadValue : public boost::noncopyable
+{
+public:
+  typedef ValueImp ValueType;
+  typedef typename std::conditional<std::is_const<ValueImp>::value, ValueImp, const ValueImp>::type ConstValueType;
+
+private:
+  typedef UnsafePerThreadValue<ValueImp> ThisType;
+  typedef std::deque<std::unique_ptr<ValueType>> ContainerType;
+
+public:
+  //! Initialization by copy construction of ValueType
+  explicit UnsafePerThreadValue(ConstValueType& value)
+    : values_(threadManager().max_threads())
+  {
+    std::generate(values_.begin(), values_.end(), [=]() { return Common::make_unique<ValueType>(value); });
+  }
+
+  //! Initialization by in-place construction ValueType with \param ctor_args
+  template <class... InitTypes>
+  explicit UnsafePerThreadValue(InitTypes&&... ctor_args)
+    : values_(threadManager().max_threads())
+  {
+    for (auto&& val : values_)
+      val = Common::make_unique<ValueType>(ctor_args...);
+  }
+
+  ThisType& operator=(ConstValueType&& value)
+  {
+    std::generate(values_.begin(), values_.end(), [=]() { return Common::make_unique<ValueType>(value); });
+    return *this;
+  }
+
+  operator ValueType() const
+  {
+    return this->operator*();
+  }
+
+  ValueType& operator*()
+  {
+    return *values_[threadManager().thread()];
+  }
+
+  ConstValueType& operator*() const
+  {
+    return *values_[threadManager().thread()];
+  }
+
+  ValueType* operator->()
+  {
+    return values_[threadManager().thread()].get();
+  }
+
+  ConstValueType* operator->() const
+  {
+    return values_[threadManager().thread()].get();
+  }
+
+  auto& get_pointer()
+  {
+    return values_[threadManager().thread()];
+  }
+
+  template <class BinaryOperation>
+  ValueType accumulate(ValueType init, BinaryOperation op) const
+  {
+    typedef const typename ContainerType::value_type ptr;
+    auto l = [&](ConstValueType& a, ptr& b) { return op(a, *b); };
+    return std::accumulate(values_.begin(), values_.end(), init, l);
+  }
+
+  ValueType sum() const
+  {
+    return accumulate(ValueType(0), std::plus<ValueType>());
+  }
+
+  typename ContainerType::iterator begin()
+  {
+    return values_.begin();
+  }
+  typename ContainerType::iterator end()
+  {
+    return values_.end();
+  }
+
+  typename ContainerType::const_iterator begin() const
+  {
+    return values_.begin();
+  }
+  typename ContainerType::const_iterator end() const
+  {
+    return values_.end();
+  }
+
+private:
+  ContainerType values_;
+}; // class UnsafePerThreadValue<...>
+
+
 template <class Imp, typename Result, class Reduction = std::plus<Result>>
 class ThreadResultPropagator
 {
diff --git a/dune/xt/common/timings.cc b/dune/xt/common/timings.cc
index 658ba3de9e260f130b1d6828ef4d57d2cfdb1599..ecde894b7a2e6e90337e059fabd8f3ff9c30fc9d 100644
--- a/dune/xt/common/timings.cc
+++ b/dune/xt/common/timings.cc
@@ -98,12 +98,11 @@ void Timings::start(std::string section_name)
   if (section != known_timers_map_.end()) {
     if (section->second.first) // timer currently running
       return;
-
     section->second.first = true; // set active, start with new
-    section->second.second = PerThreadValue<TimingData>(section_name);
+    section->second.second = TimingData(section_name);
   } else {
     // init new section
-    known_timers_map_[section_name] = std::make_pair(true, PerThreadValue<TimingData>(section_name));
+    known_timers_map_[section_name] = std::make_pair(true, TimingData(section_name));
   }
   DXTC_LIKWID_BEGIN_SECTION(section_name)
 } // StartTiming
diff --git a/dune/xt/common/timings.hh b/dune/xt/common/timings.hh
index 2af4ad4ce3a930704cd75072516e78d6498589db..87220c07189303dcc2fd58a0c79847af8e2fdaf2 100644
--- a/dune/xt/common/timings.hh
+++ b/dune/xt/common/timings.hh
@@ -82,7 +82,7 @@ class Timings
 private:
   Timings();
 
-  typedef std::map<std::string, std::pair<std::atomic<bool>, PerThreadValue<TimingData>>> KnownTimersMap;
+  typedef std::map<std::string, std::pair<std::atomic<bool>, UnsafePerThreadValue<TimingData>>> KnownTimersMap;
   //! section name -> seconds
   typedef std::map<std::string, TimingData::DeltaType> DeltaMap;