diff --git a/pressure-vessel/runtime.c b/pressure-vessel/runtime.c
index 34549a97b2e89ad72db2a57ce8c06cb2f9260956..9932d5dae7774198ff3cd3be7968a4c5df567a5f 100644
--- a/pressure-vessel/runtime.c
+++ b/pressure-vessel/runtime.c
@@ -644,16 +644,10 @@ pv_runtime_garbage_collect (PvRuntime *self,
   return TRUE;
 }
 
-static gboolean pv_runtime_create_copy (PvRuntime *self,
-                                        PvBwrapLock *variable_dir_lock,
-                                        GError **error);
-
 static gboolean
-pv_runtime_init_mutable (PvRuntime *self,
-                         GError **error)
+pv_runtime_init_variable_dir (PvRuntime *self,
+                              GError **error)
 {
-  g_autoptr(PvBwrapLock) mutable_lock = NULL;
-
   /* Nothing to do in this case */
   if (self->variable_dir == NULL)
     return TRUE;
@@ -666,32 +660,28 @@ pv_runtime_init_mutable (PvRuntime *self,
                        &self->variable_dir_fd, error))
     return FALSE;
 
-  /* Lock the parent directory. Anything that directly manipulates the
-   * temporary runtimes is expected to do the same, so that
-   * it cannot be deleting temporary runtimes at the same time we're
-   * creating them.
-   *
-   * This is a read-mode lock: it's OK to create more than one temporary
-   * runtime in parallel, as long as nothing is deleting them
-   * concurrently. */
-  mutable_lock = pv_bwrap_lock_new (self->variable_dir_fd, ".ref",
-                                    PV_BWRAP_LOCK_FLAGS_CREATE,
-                                    error);
-
-  if (mutable_lock == NULL)
-    return glnx_prefix_error (error, "Unable to lock \"%s/%s\"",
-                              self->variable_dir, ".ref");
-
   /* GC old runtimes (if they have become unused) before we create a
    * new one. This means we should only ever have one temporary runtime
    * copy per game that is run concurrently. */
-  if ((self->flags & PV_RUNTIME_FLAGS_GC_RUNTIMES) != 0 &&
-      !pv_runtime_garbage_collect (self, mutable_lock, error))
-    return FALSE;
+  if (self->flags & PV_RUNTIME_FLAGS_GC_RUNTIMES)
+    {
+      g_autoptr(PvBwrapLock) mutable_lock = NULL;
+      g_autoptr(GError) local_error = NULL;
 
-  if ((self->flags & PV_RUNTIME_FLAGS_COPY_RUNTIME) != 0
-      && !pv_runtime_create_copy (self, mutable_lock, error))
-    return FALSE;
+      /* Take out an exclusive lock for GC so that we will not conflict
+       * with other concurrent processes that are halfway through
+       * deploying or unpacking a runtime. */
+      mutable_lock = pv_bwrap_lock_new (self->variable_dir_fd, ".ref",
+                                        (PV_BWRAP_LOCK_FLAGS_CREATE
+                                         | PV_BWRAP_LOCK_FLAGS_WRITE),
+                                        &local_error);
+
+      if (mutable_lock == NULL)
+        g_debug ("Unable to take an exclusive lock, skipping GC: %s",
+                 local_error->message);
+      else if (!pv_runtime_garbage_collect (self, mutable_lock, error))
+        return FALSE;
+    }
 
   return TRUE;
 }
@@ -882,6 +872,9 @@ pv_runtime_initable_init (GInitable *initable,
                          self->variable_dir);
     }
 
+  if (!pv_runtime_init_variable_dir (self, error))
+    return FALSE;
+
   if (!g_file_test (self->deployment, G_FILE_TEST_IS_DIR))
     {
       return glnx_throw (error, "\"%s\" is not a directory",
@@ -927,8 +920,29 @@ pv_runtime_initable_init (GInitable *initable,
   if (self->runtime_lock == NULL)
     return FALSE;
 
-  if (!pv_runtime_init_mutable (self, error))
-    return FALSE;
+  if (self->flags & PV_RUNTIME_FLAGS_COPY_RUNTIME)
+    {
+      g_autoptr(PvBwrapLock) mutable_lock = NULL;
+
+      if (self->variable_dir_fd < 0)
+        return glnx_throw (error,
+                           "Cannot copy runtime without variable directory");
+
+      /* This time take out a non-exclusive lock: any number of processes
+       * can safely be creating their own temporary copy at the same
+       * time. If another process is doing GC, wait for it to finish,
+       * then take our lock. */
+      mutable_lock = pv_bwrap_lock_new (self->variable_dir_fd, ".ref",
+                                        (PV_BWRAP_LOCK_FLAGS_CREATE
+                                         | PV_BWRAP_LOCK_FLAGS_WAIT),
+                                        error);
+
+      if (mutable_lock == NULL)
+        return FALSE;
+
+      if (!pv_runtime_create_copy (self, mutable_lock, error))
+        return FALSE;
+    }
 
   if (self->mutable_sysroot != NULL)
     {