diff --git a/lib/fake_sqs/memory_database.rb b/lib/fake_sqs/memory_database.rb
index <HASH>..<HASH> 100644
--- a/lib/fake_sqs/memory_database.rb
+++ b/lib/fake_sqs/memory_database.rb
@@ -1,4 +1,5 @@
 require "forwardable"
+require "thread"
 
 module FakeSQS
   class MemoryDatabase
@@ -8,7 +9,7 @@ module FakeSQS
       :[], :[]=, :delete, :each, :select, :values
 
     def initialize
-      @in_transaction = false
+      @semaphore = Mutex.new
     end
 
     def load
@@ -16,15 +17,8 @@ module FakeSQS
     end
 
     def transaction
-      if @in_transaction
-        raise "Already in transaction"
-      else
-        @in_transaction = true
-        begin
-          yield
-        ensure
-          @in_transaction = false
-        end
+      @semaphore.synchronize do
+        yield
       end
     end
Use a Mutex to make MemoryDatabase genuinely thread safe.

While the "check and raise" boolean method sometimes works, it quickly
starts raising errors and spamming the console when run under a modern
threaded server like thin or puma. Since Ruby has a reliable, genuine
mutex, use it so that instead of tossing away any conflicting
transactions, they just line up and go one at a time.