diff --git a/day3/examples/threads/false_sharing.cc b/day3/examples/threads/false_sharing.cc
new file mode 100644
index 0000000000000000000000000000000000000000..99fb80774ae6901beeb9e34d05d61a192faf2955
--- /dev/null
+++ b/day3/examples/threads/false_sharing.cc
@@ -0,0 +1,50 @@
+#include "timeit.hh"
+#include <array>
+#include <iostream>
+#include <thread>
+
+constexpr auto WORKLOAD = 1000000000UL;
+constexpr auto PARALLEL = 16UL;
+
+struct wrapped1 {
+    int val {};
+};
+struct alignas(std::hardware_destructive_interference_size) wrapped2 {
+    int val {};
+};
+
+template <class W>
+struct func {
+void operator()(volatile W* var)
+{
+    for (unsigned i = 0; i < WORKLOAD / PARALLEL; ++i) {
+        var->val = var->val + 1;
+    }
+}
+};
+
+auto main() -> int
+{
+    timeit("Different threads accumulating to different variables, but different cache lines",
+        5UL,
+        [] {
+            std::array<wrapped2, PARALLEL> arr {};
+            {
+                std::array<std::jthread, PARALLEL> threads;
+                for (unsigned i = 0U; i < PARALLEL; ++i) {
+                    threads[i] = std::jthread(func<wrapped2>{}, &arr[i]);
+                }
+            }
+        });
+    timeit("Different threads accumulating to different variables, but in the same cache line",
+        5UL,
+        [] {
+            std::array<wrapped1, PARALLEL> arr {};
+            {
+                std::array<std::jthread, PARALLEL> threads;
+                for (unsigned i = 0U; i < PARALLEL; ++i) {
+                    threads[i] = std::jthread(func<wrapped1>{}, &arr[i]);
+                }
+            }
+        });
+}
diff --git a/day3/examples/threads/jthread0.cc b/day3/examples/threads/jthread0.cc
new file mode 100644
index 0000000000000000000000000000000000000000..2df080beeb46b90e513b55a6d6d1b9eba943da86
--- /dev/null
+++ b/day3/examples/threads/jthread0.cc
@@ -0,0 +1,26 @@
+#include <cmath>
+#include <iostream>
+#include <numbers>
+#include <thread>
+
+auto main() -> int
+{
+    using std::numbers::pi;
+    constexpr auto N = 1'000'000UL;
+    std::jthread j1 { [=]() {
+        auto tot1 = 0.;
+        for (auto i = 0UL; i < N; ++i) {
+            auto ang = 2 * i * pi / N;
+            tot1 += std::cos(ang) * std::cos(ang);
+        }
+        std::cout << "Thread 1 got total " << tot1 << "\n";
+    } };
+    std::jthread j2 { [=]() {
+        auto tot2 = 0.;
+        for (auto i = 0UL; i < N; ++i) {
+            auto ang = 2 * i * pi / N;
+            tot2 += std::sin(ang) * std::sin(ang);
+        }
+        std::cout << "Thread 2 got total " << tot2 << "\n";
+    } };
+}
diff --git a/day3/examples/threads/jthread1.cc b/day3/examples/threads/jthread1.cc
new file mode 100644
index 0000000000000000000000000000000000000000..0c0080ebb58e85af94f2c6be72c3a5808f8b669e
--- /dev/null
+++ b/day3/examples/threads/jthread1.cc
@@ -0,0 +1,26 @@
+#include <cmath>
+#include <iostream>
+#include <numbers>
+#include <thread>
+
+auto main() -> int
+{
+    using std::numbers::pi;
+    constexpr auto N = 1'000'000UL;
+    auto tot = 0.;
+    {
+        std::jthread j1 { [&]() {
+            for (auto i = 0UL; i < N; ++i) {
+                auto ang = 2 * i * pi / N;
+                tot += std::cos(ang) * std::cos(ang);
+            }
+        } };
+        std::jthread j2 { [&]() {
+            for (auto i = 0UL; i < N; ++i) {
+                auto ang = 2 * i * pi / N;
+                tot += std::sin(ang) * std::sin(ang);
+            }
+        } };
+    }
+    std::cout << "Total " << tot << "\n";
+}
diff --git a/day3/examples/threads/jthread2.cc b/day3/examples/threads/jthread2.cc
new file mode 100644
index 0000000000000000000000000000000000000000..9c44de77997d42227c3e7052b98c075fd8ff0f85
--- /dev/null
+++ b/day3/examples/threads/jthread2.cc
@@ -0,0 +1,30 @@
+#include <cmath>
+#include <iostream>
+#include <mutex>
+#include <numbers>
+#include <thread>
+
+auto main() -> int
+{
+    using std::numbers::pi;
+    constexpr auto N = 1'000'000UL;
+    auto tot = 0.;
+    std::mutex totmutex;
+    {
+        std::jthread j1 { [&]() {
+            for (auto i = 0UL; i < N; ++i) {
+                auto ang = 2 * i * pi / N;
+                std::scoped_lock lck { totmutex };
+                tot += std::cos(ang) * std::cos(ang);
+            }
+        } };
+        std::jthread j2 { [&]() {
+            for (auto i = 0UL; i < N; ++i) {
+                auto ang = 2 * i * pi / N;
+                std::scoped_lock lck { totmutex };
+                tot += std::sin(ang) * std::sin(ang);
+            }
+        } };
+    }
+    std::cout << "Total " << tot << "\n";
+}
diff --git a/day3/examples/threads/jthread3.cc b/day3/examples/threads/jthread3.cc
new file mode 100644
index 0000000000000000000000000000000000000000..bc331758e484307c8ba13581c377699c5299d201
--- /dev/null
+++ b/day3/examples/threads/jthread3.cc
@@ -0,0 +1,27 @@
+#include <atomic>
+#include <cmath>
+#include <iostream>
+#include <numbers>
+#include <thread>
+
+auto main() -> int
+{
+    using std::numbers::pi;
+    constexpr auto N = 1'000'000UL;
+    std::atomic<double> tot {};
+    {
+        std::jthread j1 { [&]() {
+            for (auto i = 0UL; i < N; ++i) {
+                auto ang = 2 * i * pi / N;
+                tot += std::cos(ang) * std::cos(ang);
+            }
+        } };
+        std::jthread j2 { [&]() {
+            for (auto i = 0UL; i < N; ++i) {
+                auto ang = 2 * i * pi / N;
+                tot += std::sin(ang) * std::sin(ang);
+            }
+        } };
+    }
+    std::cout << "Total " << tot << "\n";
+}