diff --git a/core/modules/layout_builder/layout_builder.routing.yml b/core/modules/layout_builder/layout_builder.routing.yml
index b59e2a036d..9a9ff8c967 100644
--- a/core/modules/layout_builder/layout_builder.routing.yml
+++ b/core/modules/layout_builder/layout_builder.routing.yml
@@ -5,6 +5,7 @@ layout_builder.choose_section:
    _title: 'Choose a layout for this section'
   requirements:
     _layout_builder_access: 'view'
+    _layout_builder_lock_access: 'true'
   options:
     _admin_route: TRUE
     parameters:
@@ -17,6 +18,7 @@ layout_builder.add_section:
     _controller: '\Drupal\layout_builder\Controller\AddSectionController::build'
   requirements:
     _layout_builder_access: 'view'
+    _layout_builder_lock_access: 'true'
   options:
     _admin_route: TRUE
     parameters:
@@ -33,6 +35,7 @@ layout_builder.configure_section:
     plugin_id: null
   requirements:
     _layout_builder_access: 'view'
+    _layout_builder_lock_access: 'true'
   options:
     _admin_route: TRUE
     parameters:
@@ -45,6 +48,7 @@ layout_builder.remove_section:
     _form: '\Drupal\layout_builder\Form\RemoveSectionForm'
   requirements:
     _layout_builder_access: 'view'
+    _layout_builder_lock_access: 'true'
   options:
     _admin_route: TRUE
     parameters:
@@ -58,6 +62,7 @@ layout_builder.choose_block:
     _title: 'Choose a block'
   requirements:
     _layout_builder_access: 'view'
+    _layout_builder_lock_access: 'true'
   options:
     _admin_route: TRUE
     parameters:
@@ -71,6 +76,7 @@ layout_builder.add_block:
     _title: 'Configure block'
   requirements:
     _layout_builder_access: 'view'
+    _layout_builder_lock_access: 'true'
   options:
     _admin_route: TRUE
     parameters:
@@ -84,6 +90,7 @@ layout_builder.choose_inline_block:
     _title: 'Add a new Inline Block'
   requirements:
     _layout_builder_access: 'view'
+    _layout_builder_lock_access: 'true'
   options:
     _admin_route: TRUE
     parameters:
@@ -97,6 +104,7 @@ layout_builder.update_block:
     _title: 'Configure block'
   requirements:
     _layout_builder_access: 'view'
+    _layout_builder_lock_access: 'true'
   options:
     _admin_route: TRUE
     parameters:
@@ -110,6 +118,7 @@ layout_builder.move_block_form:
     _form: '\Drupal\layout_builder\Form\MoveBlockForm'
   requirements:
     _layout_builder_access: 'view'
+    _layout_builder_lock_access: 'true'
   options:
     _admin_route: TRUE
     parameters:
@@ -122,6 +131,7 @@ layout_builder.remove_block:
     _form: '\Drupal\layout_builder\Form\RemoveBlockForm'
   requirements:
     _layout_builder_access: 'view'
+    _layout_builder_lock_access: 'true'
   options:
     _admin_route: TRUE
     parameters:
@@ -140,6 +150,7 @@ layout_builder.move_block:
     preceding_block_uuid: null
   requirements:
     _layout_builder_access: 'view'
+    _layout_builder_lock_access: 'true'
   options:
     _admin_route: TRUE
     parameters:
diff --git a/core/modules/layout_builder/layout_builder.services.yml b/core/modules/layout_builder/layout_builder.services.yml
index 6e94ed74d2..abaafd9e0a 100644
--- a/core/modules/layout_builder/layout_builder.services.yml
+++ b/core/modules/layout_builder/layout_builder.services.yml
@@ -2,6 +2,11 @@ services:
   layout_builder.tempstore_repository:
     class: Drupal\layout_builder\LayoutTempstoreRepository
     arguments: ['@tempstore.shared']
+  access_check.entity.layout_builder_lock_access:
+    class: Drupal\layout_builder\Access\LayoutBuilderLockAccessCheck
+    arguments: ['@layout_builder.tempstore_repository']
+    tags:
+      - { name: access_check, applies_to: _layout_builder_lock_access }
   access_check.entity.layout_builder_access:
     class: Drupal\layout_builder\Access\LayoutBuilderAccessCheck
     tags:
diff --git a/core/modules/layout_builder/src/Access/LayoutBuilderLockAccessCheck.php b/core/modules/layout_builder/src/Access/LayoutBuilderLockAccessCheck.php
new file mode 100644
index 0000000000..7f8e8f403b
--- /dev/null
+++ b/core/modules/layout_builder/src/Access/LayoutBuilderLockAccessCheck.php
@@ -0,0 +1,54 @@
+<?php
+
+namespace Drupal\layout_builder\Access;
+
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Routing\Access\AccessInterface;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\layout_builder\LayoutTempstoreRepositoryInterface;
+use Drupal\layout_builder\SectionStorageInterface;
+
+/**
+ * Checks access based on whether the layout is locked.
+ *
+ * @ingroup layout_builder_access
+ *
+ * @internal
+ *   Tagged services are internal.
+ */
+class LayoutBuilderLockAccessCheck implements AccessInterface {
+
+  /**
+   * The layout tempstore repository.
+   *
+   * @var \Drupal\layout_builder\LayoutTempstoreRepositoryInterface
+   */
+  protected $layoutTempstoreRepository;
+
+  /**
+   * Constructs a LayoutBuilderLockAccessCheck.
+   *
+   * @param \Drupal\layout_builder\LayoutTempstoreRepositoryInterface $layout_tempstore_repository
+   *   The layout tempstore repository.
+   */
+  public function __construct(LayoutTempstoreRepositoryInterface $layout_tempstore_repository) {
+    $this->layoutTempstoreRepository = $layout_tempstore_repository;
+  }
+
+  /**
+   * Checks for a lock on the layout.
+   *
+   * @param \Drupal\layout_builder\SectionStorageInterface $section_storage
+   *   The section storage.
+   * @param \Drupal\Core\Session\AccountInterface $account
+   *   The current user.
+   *
+   * @return \Drupal\Core\Access\AccessResultInterface
+   *   The access result.
+   */
+  public function access(SectionStorageInterface $section_storage, AccountInterface $account) {
+    $lock = $this->layoutTempstoreRepository->getLock($section_storage);
+    return AccessResult::allowedIf(!$lock || $account->id() === $lock->getOwnerId())->setCacheMaxAge(0);
+  }
+
+}
diff --git a/core/modules/layout_builder/src/Controller/LayoutRebuildTrait.php b/core/modules/layout_builder/src/Controller/LayoutRebuildTrait.php
index b8664edc51..26be7af4db 100644
--- a/core/modules/layout_builder/src/Controller/LayoutRebuildTrait.php
+++ b/core/modules/layout_builder/src/Controller/LayoutRebuildTrait.php
@@ -40,11 +40,19 @@ protected function rebuildAndClose(SectionStorageInterface $section_storage) {
    */
   protected function rebuildLayout(SectionStorageInterface $section_storage) {
     $response = new AjaxResponse();
-    $layout = [
-      '#type' => 'layout_builder',
-      '#section_storage' => $section_storage,
-    ];
-    $response->addCommand(new ReplaceCommand('#layout-builder', $layout));
+
+    // Get the entity for the SectionStorage form from context.
+    $context_value = $section_storage->getPluginId() === 'overrides' ? 'entity' : 'display';
+    $entity = $section_storage->getContextValue($context_value);
+
+    // Create the updated entity form.
+    $form_object = \Drupal::entityTypeManager()->getFormObject($entity->getEntityTypeId(), 'layout_builder');
+    $form_object->setEntity($entity);
+    $form_render = \Drupal::formBuilder()->getForm($form_object, $section_storage);
+
+    // Replace the entity form with the updated version.
+    $response->addCommand(new ReplaceCommand('[data-drupal-layout-builder-entityform]', $form_render));
+
     return $response;
   }
 
diff --git a/core/modules/layout_builder/src/Element/LayoutBuilder.php b/core/modules/layout_builder/src/Element/LayoutBuilder.php
index c2154f537b..f6521772b9 100644
--- a/core/modules/layout_builder/src/Element/LayoutBuilder.php
+++ b/core/modules/layout_builder/src/Element/LayoutBuilder.php
@@ -3,7 +3,6 @@
 namespace Drupal\layout_builder\Element;
 
 use Drupal\Core\Ajax\AjaxHelperTrait;
-use Drupal\Core\Messenger\MessengerInterface;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
 use Drupal\Core\Plugin\PluginFormInterface;
 use Drupal\Core\Render\Element;
@@ -37,13 +36,6 @@ class LayoutBuilder extends RenderElement implements ContainerFactoryPluginInter
    */
   protected $layoutTempstoreRepository;
 
-  /**
-   * The messenger service.
-   *
-   * @var \Drupal\Core\Messenger\MessengerInterface
-   */
-  protected $messenger;
-
   /**
    * Constructs a new LayoutBuilder.
    *
@@ -55,13 +47,10 @@ class LayoutBuilder extends RenderElement implements ContainerFactoryPluginInter
    *   The plugin implementation definition.
    * @param \Drupal\layout_builder\LayoutTempstoreRepositoryInterface $layout_tempstore_repository
    *   The layout tempstore repository.
-   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
-   *   The messenger service.
    */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, LayoutTempstoreRepositoryInterface $layout_tempstore_repository, MessengerInterface $messenger) {
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, LayoutTempstoreRepositoryInterface $layout_tempstore_repository) {
     parent::__construct($configuration, $plugin_id, $plugin_definition);
     $this->layoutTempstoreRepository = $layout_tempstore_repository;
-    $this->messenger = $messenger;
   }
 
   /**
@@ -72,8 +61,7 @@ public static function create(ContainerInterface $container, array $configuratio
       $configuration,
       $plugin_id,
       $plugin_definition,
-      $container->get('layout_builder.tempstore_repository'),
-      $container->get('messenger')
+      $container->get('layout_builder.tempstore_repository')
     );
   }
 
@@ -145,13 +133,9 @@ protected function layout(SectionStorageInterface $section_storage) {
    *   The section storage.
    */
   protected function prepareLayout(SectionStorageInterface $section_storage) {
-    // If the layout has pending changes, add a warning.
-    if ($this->layoutTempstoreRepository->has($section_storage)) {
-      $this->messenger->addWarning($this->t('You have unsaved changes.'));
-    }
     // If the layout is an override that has not yet been overridden, copy the
     // sections from the corresponding default.
-    elseif ($section_storage instanceof OverridesSectionStorageInterface && !$section_storage->isOverridden()) {
+    if ($section_storage instanceof OverridesSectionStorageInterface && !$section_storage->isOverridden() && !$this->layoutTempstoreRepository->has($section_storage)) {
       $sections = $section_storage->getDefaultSectionStorage()->getSections();
       foreach ($sections as $section) {
         $section_storage->appendSection($section);
diff --git a/core/modules/layout_builder/src/EventSubscriber/BlockComponentRenderArray.php b/core/modules/layout_builder/src/EventSubscriber/BlockComponentRenderArray.php
index e1a9773959..29a1523d0b 100644
--- a/core/modules/layout_builder/src/EventSubscriber/BlockComponentRenderArray.php
+++ b/core/modules/layout_builder/src/EventSubscriber/BlockComponentRenderArray.php
@@ -102,6 +102,14 @@ public function onBuildRender(SectionComponentBuildRenderArrayEvent $event) {
       }
 
       $content = $block->build();
+
+      // If this is the Layout Builder UI and the content is a form, remove
+      // #theme_wrappers so the content rendering does not disrupt the creation
+      // of CSRF tokens for the Layout Builder entity form.
+      if (isset($content['#type']) && $content['#type'] === 'form' && $event->inPreview()) {
+        unset($content['#theme_wrappers']);
+      }
+
       $is_content_empty = Element::isEmpty($content);
       $is_placeholder_ready = $event->inPreview() && $block instanceof PreviewFallbackInterface;
       // If the content is empty and no placeholder is available, return.
diff --git a/core/modules/layout_builder/src/Form/DefaultsEntityForm.php b/core/modules/layout_builder/src/Form/DefaultsEntityForm.php
index e26a55c7d2..044632684a 100644
--- a/core/modules/layout_builder/src/Form/DefaultsEntityForm.php
+++ b/core/modules/layout_builder/src/Form/DefaultsEntityForm.php
@@ -19,6 +19,7 @@
  */
 class DefaultsEntityForm extends EntityForm {
 
+  use LayoutBuilderEntityFormTrait;
   use PreviewToggleTrait;
 
   /**
@@ -80,13 +81,21 @@ public function getBaseFormId() {
    * {@inheritdoc}
    */
   public function buildForm(array $form, FormStateInterface $form_state, SectionStorageInterface $section_storage = NULL) {
+    if ($lock_message = $this->getLockMessage($section_storage)) {
+      return $lock_message;
+    }
+
     $form['layout_builder'] = [
       '#type' => 'layout_builder',
       '#section_storage' => $section_storage,
     ];
     $form['layout_builder_message'] = $this->buildMessage($section_storage->getContextValue('display'));
+    $form['#attributes']['data-drupal-layout-builder-entityform'] = "";
+
+    // #action must be explicitly set so it is not changed when the form is
+    // rebuilt via ajax.
+    $form['#action'] = $section_storage->getLayoutBuilderUrl()->toString();
 
-    $this->sectionStorage = $section_storage;
     return parent::buildForm($form, $form_state);
   }
 
@@ -171,6 +180,12 @@ protected function actions(array $form, FormStateInterface $form_state) {
       '#redirect' => 'discard_changes',
     ];
     $actions['preview_toggle'] = $this->buildContentPreviewToggle();
+
+    // Restrict access to actions if the form is locked by another user.
+    $lock = $this->layoutTempstoreRepository->getLock($this->sectionStorage);
+    if ($lock && $lock->getOwnerId() !== $this->currentUser()->id()) {
+      $actions['#access'] = FALSE;
+    }
     return $actions;
   }
 
@@ -186,9 +201,7 @@ public function redirectOnSubmit(array $form, FormStateInterface $form_state) {
    */
   public function save(array $form, FormStateInterface $form_state) {
     $return = $this->sectionStorage->save();
-    $this->layoutTempstoreRepository->delete($this->sectionStorage);
-    $this->messenger()->addMessage($this->t('The layout has been saved.'));
-    $form_state->setRedirectUrl($this->sectionStorage->getRedirectUrl());
+    $this->layoutEntitySaveTasks($form_state);
     return $return;
   }
 
diff --git a/core/modules/layout_builder/src/Form/DiscardLayoutChangesForm.php b/core/modules/layout_builder/src/Form/DiscardLayoutChangesForm.php
index 5f49f298a8..2b99c2f729 100644
--- a/core/modules/layout_builder/src/Form/DiscardLayoutChangesForm.php
+++ b/core/modules/layout_builder/src/Form/DiscardLayoutChangesForm.php
@@ -5,6 +5,7 @@
 use Drupal\Core\Form\ConfirmFormBase;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Messenger\MessengerInterface;
+use Drupal\Core\Session\AccountInterface;
 use Drupal\layout_builder\LayoutTempstoreRepositoryInterface;
 use Drupal\layout_builder\SectionStorageInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -31,6 +32,13 @@ class DiscardLayoutChangesForm extends ConfirmFormBase {
    */
   protected $messenger;
 
+  /**
+   * The current user.
+   *
+   * @var \Drupal\Core\Session\AccountInterface
+   */
+  protected $currentUser;
+
   /**
    * The section storage.
    *
@@ -38,6 +46,13 @@ class DiscardLayoutChangesForm extends ConfirmFormBase {
    */
   protected $sectionStorage;
 
+  /**
+   * Indicates if the owner of the lock is the current user or not.
+   *
+   * @var bool
+   */
+  protected $isOwnerCurrentUser;
+
   /**
    * Constructs a new DiscardLayoutChangesForm.
    *
@@ -45,10 +60,13 @@ class DiscardLayoutChangesForm extends ConfirmFormBase {
    *   The layout tempstore repository.
    * @param \Drupal\Core\Messenger\MessengerInterface $messenger
    *   The messenger service.
+   * @param \Drupal\Core\Session\AccountInterface $current_user
+   *   The current user.
    */
-  public function __construct(LayoutTempstoreRepositoryInterface $layout_tempstore_repository, MessengerInterface $messenger) {
+  public function __construct(LayoutTempstoreRepositoryInterface $layout_tempstore_repository, MessengerInterface $messenger, AccountInterface $current_user) {
     $this->layoutTempstoreRepository = $layout_tempstore_repository;
     $this->messenger = $messenger;
+    $this->currentUser = $current_user;
   }
 
   /**
@@ -57,7 +75,8 @@ public function __construct(LayoutTempstoreRepositoryInterface $layout_tempstore
   public static function create(ContainerInterface $container) {
     return new static(
       $container->get('layout_builder.tempstore_repository'),
-      $container->get('messenger')
+      $container->get('messenger'),
+      $container->get('current_user')
     );
   }
 
@@ -72,14 +91,14 @@ public function getFormId() {
    * {@inheritdoc}
    */
   public function getQuestion() {
-    return $this->t('Are you sure you want to discard your layout changes?');
+    return $this->isOwnerCurrentUser ? $this->t('Are you sure you want to discard your layout changes?') : $this->t('Are you sure you want to break the lock on the layout changes?');
   }
 
   /**
    * {@inheritdoc}
    */
   public function getCancelUrl() {
-    return $this->sectionStorage->getRedirectUrl();
+    return $this->sectionStorage->getLayoutBuilderUrl();
   }
 
   /**
@@ -87,6 +106,12 @@ public function getCancelUrl() {
    */
   public function buildForm(array $form, FormStateInterface $form_state, SectionStorageInterface $section_storage = NULL) {
     $this->sectionStorage = $section_storage;
+    $lock = $this->layoutTempstoreRepository->getLock($section_storage);
+
+    // The current user is considered the owner if they are the ones who made
+    // the changes or if there are no changes made.
+    $this->isOwnerCurrentUser = $lock ? $lock->getOwnerId() === $this->currentUser()->id() : TRUE;
+
     // Mark this as an administrative page for JavaScript ("Back to site" link).
     $form['#attached']['drupalSettings']['path']['currentPathIsAdmin'] = TRUE;
     return parent::buildForm($form, $form_state);
@@ -100,7 +125,10 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
 
     $this->messenger->addMessage($this->t('The changes to the layout have been discarded.'));
 
-    $form_state->setRedirectUrl($this->getCancelUrl());
+    // If the user is discarding their own changes, redirect as usual. If they
+    // are breaking the lock of another user's changes, redirect them back to
+    // the Layout Builder UI to make their own changes.
+    $form_state->setRedirectUrl($this->isOwnerCurrentUser ? $this->sectionStorage->getRedirectUrl() : $this->sectionStorage->getLayoutBuilderUrl());
   }
 
 }
diff --git a/core/modules/layout_builder/src/Form/LayoutBuilderEntityFormTrait.php b/core/modules/layout_builder/src/Form/LayoutBuilderEntityFormTrait.php
new file mode 100644
index 0000000000..45a09643ec
--- /dev/null
+++ b/core/modules/layout_builder/src/Form/LayoutBuilderEntityFormTrait.php
@@ -0,0 +1,111 @@
+<?php
+
+namespace Drupal\layout_builder\Form;
+
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\TempStore\Lock;
+use Drupal\layout_builder\SectionStorageInterface;
+
+/**
+ * A trait for functionality used by both types of entity forms.
+ */
+trait LayoutBuilderEntityFormTrait {
+
+  /**
+   * The layout tempstore repository.
+   *
+   * @var \Drupal\layout_builder\LayoutTempstoreRepositoryInterface
+   */
+  protected $layoutTempstoreRepository;
+
+
+  /**
+   * The section storage.
+   *
+   * @var \Drupal\layout_builder\SectionStorageInterface
+   */
+  protected $sectionStorage;
+
+  /**
+   * Gets the current user.
+   *
+   * @return \Drupal\Core\Session\AccountInterface
+   *   The current user.
+   */
+  abstract protected function currentUser();
+
+  /**
+   * Gets the messenger service.
+   *
+   * @return \Drupal\Core\Messenger\MessengerInterface
+   *   The messenger service.
+   */
+  abstract protected function messenger();
+
+  /**
+   * Checks if a lock is present and provides a situation specific message.
+   *
+   * @param \Drupal\layout_builder\SectionStorageInterface $section_storage
+   *   The section storage to get the lock from.
+   *
+   * @return array|null
+   *   If the section storage is locked and does not belong to current user,
+   *   return a render array that will replace the Layout Builder UI form.
+   *   Otherwise, return null.
+   */
+  protected function getLockMessage(SectionStorageInterface $section_storage) {
+    if ($lock = $this->layoutTempstoreRepository->getLock($section_storage)) {
+      if ($this->currentUser()->id() === $lock->getOwnerId()) {
+        $this->messenger()->addWarning($this->t('You have unsaved changes.'));
+      }
+      else {
+        return $this->lockMessage($section_storage, $lock);
+      }
+    }
+    return NULL;
+  }
+
+  /**
+   * Builds the lock message.
+   *
+   * @param \Drupal\layout_builder\SectionStorageInterface $section_storage
+   *   The section storage.
+   * @param \Drupal\Core\TempStore\Lock $lock
+   *   The lock object.
+   *
+   * @return array
+   *   A render array.
+   */
+  protected function lockMessage(SectionStorageInterface $section_storage, Lock $lock) {
+    return [
+      '#theme' => 'status_messages',
+      '#message_list' => [
+        'warning' => [
+          [
+            '#type' => 'break_lock_link',
+            '#label' => $this->t('layout'),
+            '#lock' => $lock,
+            '#url' => $section_storage->getLayoutBuilderUrl('discard_changes'),
+          ],
+        ],
+      ],
+      '#status_headings' => [
+        'warning' => $this->t('Warning message'),
+      ],
+    ];
+  }
+
+  /**
+   * Steps shared when saving override and default section storage.
+   *
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *   The form state of the Layout Builder UI form.
+   */
+  protected function layoutEntitySaveTasks(FormStateInterface $form_state) {
+    $this->layoutTempstoreRepository->delete($this->sectionStorage);
+    $this->messenger()->deleteByType('warning');
+    $this->messenger()->addMessage($this->t('The layout has been saved.'));
+    $form_state->setRedirectUrl($this->sectionStorage->getRedirectUrl());
+  }
+
+}
diff --git a/core/modules/layout_builder/src/Form/OverridesEntityForm.php b/core/modules/layout_builder/src/Form/OverridesEntityForm.php
index ac1282202a..00c7ce79af 100644
--- a/core/modules/layout_builder/src/Form/OverridesEntityForm.php
+++ b/core/modules/layout_builder/src/Form/OverridesEntityForm.php
@@ -23,6 +23,7 @@
  */
 class OverridesEntityForm extends ContentEntityForm {
 
+  use LayoutBuilderEntityFormTrait;
   use PreviewToggleTrait;
 
   /**
@@ -95,6 +96,10 @@ protected function init(FormStateInterface $form_state) {
    * {@inheritdoc}
    */
   public function buildForm(array $form, FormStateInterface $form_state, SectionStorageInterface $section_storage = NULL) {
+    if ($lock_message = $this->getLockMessage($section_storage)) {
+      return $lock_message;
+    }
+
     $this->sectionStorage = $section_storage;
     $form = parent::buildForm($form, $form_state);
 
@@ -103,7 +108,12 @@ public function buildForm(array $form, FormStateInterface $form_state, SectionSt
     //   https://www.drupal.org/node/2942975 is resolved.
     $form[OverridesSectionStorage::FIELD_NAME]['#access'] = TRUE;
 
+    // #action must be explicitly set so it is not changed when the form is
+    // rebuilt via ajax.
+    $form['#action'] = $this->entity->toUrl('canonical')->toString() . '/layout';
     $form['layout_builder_message'] = $this->buildMessage($section_storage->getContextValue('entity'), $section_storage);
+    $form['#attributes']['data-drupal-layout-builder-entityform'] = "";
+
     return $form;
   }
 
@@ -176,6 +186,7 @@ public function save(array $form, FormStateInterface $form_state) {
     $return = parent::save($form, $form_state);
 
     $this->layoutTempstoreRepository->delete($this->sectionStorage);
+    $this->messenger()->deleteByType('warning');
     $this->messenger()->addStatus($this->t('The layout override has been saved.'));
     $form_state->setRedirectUrl($this->sectionStorage->getRedirectUrl());
     return $return;
@@ -207,6 +218,12 @@ protected function actions(array $form, FormStateInterface $form_state) {
       '#redirect' => 'revert',
     ];
     $actions['preview_toggle'] = $this->buildContentPreviewToggle();
+
+    // Restrict access to actions if the form is locked by another user.
+    $lock = $this->layoutTempstoreRepository->getLock($this->sectionStorage);
+    if ($lock && $lock->getOwnerId() !== $this->currentUser()->id()) {
+      $actions['#access'] = FALSE;
+    }
     return $actions;
   }
 
diff --git a/core/modules/layout_builder/src/LayoutTempstoreRepository.php b/core/modules/layout_builder/src/LayoutTempstoreRepository.php
index 36b78948b3..7535de2ec3 100644
--- a/core/modules/layout_builder/src/LayoutTempstoreRepository.php
+++ b/core/modules/layout_builder/src/LayoutTempstoreRepository.php
@@ -43,6 +43,14 @@ public function get(SectionStorageInterface $section_storage) {
     return $section_storage;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getLock(SectionStorageInterface $section_storage) {
+    $key = $this->getKey($section_storage);
+    return $this->getTempstore($section_storage)->getMetadata($key);
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/layout_builder/src/LayoutTempstoreRepositoryInterface.php b/core/modules/layout_builder/src/LayoutTempstoreRepositoryInterface.php
index a4220b00f1..c58ce19e9d 100644
--- a/core/modules/layout_builder/src/LayoutTempstoreRepositoryInterface.php
+++ b/core/modules/layout_builder/src/LayoutTempstoreRepositoryInterface.php
@@ -22,6 +22,17 @@ interface LayoutTempstoreRepositoryInterface {
    */
   public function get(SectionStorageInterface $section_storage);
 
+  /**
+   * Returns the lock object.
+   *
+   * @param \Drupal\layout_builder\SectionStorageInterface $section_storage
+   *   The section storage.
+   *
+   * @return \Drupal\Core\TempStore\Lock|null
+   *   The lock object, or NULL if none exists.
+   */
+  public function getLock(SectionStorageInterface $section_storage);
+
   /**
    * Stores this section storage in tempstore.
    *
diff --git a/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php b/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php
index cde6f497c5..ffde1e9c09 100644
--- a/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php
+++ b/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php
@@ -148,6 +148,23 @@ public function getStorageId() {
     return $entity->getEntityTypeId() . '.' . $entity->id();
   }
 
+  /**
+   * Returns the ID of the layout entity form for this plugin.
+   *
+   * @return string
+   *   The form ID for this layout's entity form.
+   */
+  public function getEntityFormId() {
+    $entity = $this->getEntity();
+    $type = $entity->getEntityTypeId();
+    $bundle = $entity->bundle();
+    $id_parts = [$bundle, 'layout-builder-form'];
+    if ($type !== $bundle) {
+      array_unshift($id_parts, $type);
+    }
+    return implode('-', $id_parts);
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/layout_builder/tests/src/Functional/LayoutBuilderTest.php b/core/modules/layout_builder/tests/src/Functional/LayoutBuilderTest.php
index 5511c5fa6d..df922c2cae 100644
--- a/core/modules/layout_builder/tests/src/Functional/LayoutBuilderTest.php
+++ b/core/modules/layout_builder/tests/src/Functional/LayoutBuilderTest.php
@@ -765,6 +765,72 @@ public function testFullViewModeMultipleBundles() {
     $assert_session->checkboxChecked('layout[allow_custom]');
   }
 
+  /**
+   * Tests concurrent editing of the layout by two users.
+   */
+  public function testConcurrentEditing() {
+    $assert_session = $this->assertSession();
+    $page = $this->getSession()->getPage();
+
+    $user1 = $this->drupalCreateUser([
+      'configure any layout',
+      'administer node display',
+    ]);
+    $user2 = $this->drupalCreateUser([
+      'configure any layout',
+      'administer node display',
+    ]);
+
+    $this->drupalLogin($user1);
+    $this->drupalPostForm('admin/structure/types/manage/bundle_with_section_field/display/default', ['layout[enabled]' => TRUE], 'Save');
+
+    $this->drupalGet('admin/structure/types/manage/bundle_with_section_field/display/default/layout');
+    $assert_session->elementsCount('css', '.layout-builder__section', 1);
+    $assert_session->elementNotExists('css', '.layout--twocol-section');
+    $page->clickLink('Add section');
+    $page->clickLink('Two column');
+    $page->pressButton('Add section');
+    $assert_session->elementsCount('css', '.layout-builder__section', 2);
+    $assert_session->elementExists('css', '.layout--twocol-section');
+    $assert_session->pageTextContains('You have unsaved changes.');
+    $assert_session->buttonExists('Save layout');
+    $assert_session->buttonExists('Discard changes');
+    $this->drupalGet('layout_builder/choose/section/defaults/node.bundle_with_section_field.default/0');
+    $assert_session->statusCodeEquals(200);
+    $this->drupalLogout();
+
+    $this->drupalLogin($user2);
+    $this->drupalGet('admin/structure/types/manage/bundle_with_section_field/display/default/layout');
+    $assert_session->elementsCount('css', '.layout-builder__section', 0);
+    $assert_session->pageTextContains(sprintf('This layout is being edited by user %s, and is therefore locked from editing by others.', $user1->getDisplayName()));
+    $assert_session->pageTextNotContains('You have unsaved changes.');
+    $assert_session->buttonNotExists('Save layout');
+    $assert_session->buttonNotExists('Discard changes');
+    $this->drupalGet('layout_builder/choose/section/defaults/node.bundle_with_section_field.default/0');
+    $assert_session->statusCodeEquals(403);
+
+    // Confirm the tempstore is storing this layout in progress.
+    $layout_tempstore_before = $this->container->get('tempstore.shared')->get('layout_builder.section_storage.defaults')->getMetadata('node.bundle_with_section_field.default');
+    $this->assertNotNull($layout_tempstore_before);
+
+    $this->drupalGet('admin/structure/types/manage/bundle_with_section_field/display/default/layout');
+    $page->clickLink('break this lock');
+    $page->pressButton('Confirm');
+
+    // Confirm the tempstore is no longer storing anything for this layout.
+    $layout_tempstore_after = $this->container->get('tempstore.shared')->get('layout_builder.section_storage.defaults')->getMetadata('node.bundle_with_section_field.default');
+    $this->assertNull($layout_tempstore_after);
+
+    $assert_session->pageTextNotContains(sprintf('This layout is being edited by user %s, and is therefore locked from editing by others.', $user1->getDisplayName()));
+    $assert_session->elementsCount('css', '.layout-builder__section', 1);
+    $assert_session->elementNotExists('css', '.layout--twocol-section');
+    $assert_session->pageTextNotContains(sprintf('This layout is being edited by user %s, and is therefore locked from editing by others.', $user1->getDisplayName()));
+    $assert_session->pageTextNotContains('You have unsaved changes.');
+    $assert_session->pageTextContains('The changes to the layout have been discarded.');
+    $assert_session->buttonExists('Save layout');
+    $assert_session->buttonExists('Discard changes');
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/layout_builder/tests/src/Functional/Update/TempstoreKeyUpdatePathTest.php b/core/modules/layout_builder/tests/src/Functional/Update/TempstoreKeyUpdatePathTest.php
index 17afb1ca82..b220525d3f 100644
--- a/core/modules/layout_builder/tests/src/Functional/Update/TempstoreKeyUpdatePathTest.php
+++ b/core/modules/layout_builder/tests/src/Functional/Update/TempstoreKeyUpdatePathTest.php
@@ -3,6 +3,7 @@
 namespace Drupal\Tests\layout_builder\Functional\Update;
 
 use Drupal\FunctionalTests\Update\UpdatePathTestBase;
+use Drupal\user\Entity\User;
 
 /**
  * Tests the upgrade path for Layout Builder tempstore keys.
@@ -26,7 +27,7 @@ protected function setDatabaseDumpFiles() {
   }
 
   /**
-   * Tests the upgrade path for Layout Builder extra fields.
+   * Tests the upgrade path for Layout Builder tempstore keys.
    */
   public function testRunUpdates() {
     $page = $this->getSession()->getPage();
@@ -34,18 +35,22 @@ public function testRunUpdates() {
 
     $this->runUpdates();
 
-    $this->drupalLogin($this->drupalCreateUser([
+    $account = $this->drupalCreateUser([
       'configure any layout',
       'administer node display',
-    ]));
+    ]);
+    $this->drupalLogin($account);
     $this->drupalGet('node/1');
     $assert_session->elementExists('css', '.layout--onecol');
     $assert_session->elementNotExists('css', '.layout--twocol-section');
 
     $page->clickLink('Layout');
-    $assert_session->pageTextContains('You have unsaved changes.');
-    $assert_session->elementNotExists('css', '.layout--onecol');
-    $assert_session->elementExists('css', '.layout--twocol-section');
+    // User 1 is the owner of the lock and is not the current user.
+    $this->assertNotSame(1, $account->id());
+    $user = User::load(1);
+    $assert_session->pageTextContains(sprintf('This layout is being edited by user %s, and is therefore locked from editing by others.', $user->getDisplayName()));
+    $assert_session->elementNotExists('css', '.layout');
+    $assert_session->elementNotExists('css', '.layout--twocol-section');
   }
 
 }
diff --git a/core/modules/layout_builder/tests/src/FunctionalJavascript/ContextualLinksTest.php b/core/modules/layout_builder/tests/src/FunctionalJavascript/ContextualLinksTest.php
index ea0d170085..dc9d9a7add 100644
--- a/core/modules/layout_builder/tests/src/FunctionalJavascript/ContextualLinksTest.php
+++ b/core/modules/layout_builder/tests/src/FunctionalJavascript/ContextualLinksTest.php
@@ -122,6 +122,7 @@ protected function addBlock($block_name) {
   protected function assertCorrectContextualLinksInUi() {
     $assert_session = $this->assertSession();
     $page = $this->getSession()->getPage();
+
     $this->assertNotEmpty($assert_session->waitForElementVisible('css', '.block-views-blocktest-block-view-block-2'));
 
     $layout_builder_specific_contextual_links = $page->findAll('css', '[data-contextual-id*=\'layout_builder_block:\']');
diff --git a/core/modules/layout_builder/tests/src/FunctionalJavascript/InlineBlockTest.php b/core/modules/layout_builder/tests/src/FunctionalJavascript/InlineBlockTest.php
index a256b25399..b0fbd8a751 100644
--- a/core/modules/layout_builder/tests/src/FunctionalJavascript/InlineBlockTest.php
+++ b/core/modules/layout_builder/tests/src/FunctionalJavascript/InlineBlockTest.php
@@ -542,7 +542,7 @@ public function testAddInlineBlocksPermission() {
    * Tests 'create and edit custom blocks' permission to edit an existing block.
    */
   public function testEditInlineBlocksPermission() {
-    $assert_session = $this->assertSession();
+    $page = $this->getSession()->getPage();
 
     LayoutBuilderEntityViewDisplay::load('node.bundle_with_section_field.default')
       ->enableLayoutBuilder()
@@ -557,6 +557,7 @@ public function testEditInlineBlocksPermission() {
     ]));
     $this->drupalGet(static::FIELD_UI_PREFIX . '/display/default/layout');
     $this->addInlineBlockToLayout('The block label', 'The body value');
+    $page->pressButton('Save layout');
 
     $assert = function ($permissions, $expected) {
       $assert_session = $this->assertSession();
diff --git a/core/modules/layout_builder/tests/src/FunctionalJavascript/LayoutBuilderDisableInteractionsTest.php b/core/modules/layout_builder/tests/src/FunctionalJavascript/LayoutBuilderDisableInteractionsTest.php
index 8dcd507c8d..e5c093e372 100644
--- a/core/modules/layout_builder/tests/src/FunctionalJavascript/LayoutBuilderDisableInteractionsTest.php
+++ b/core/modules/layout_builder/tests/src/FunctionalJavascript/LayoutBuilderDisableInteractionsTest.php
@@ -104,14 +104,13 @@ public function testFormsLinksDisabled() {
     $this->clickLink('Manage layout');
 
     // Add a block with a form, another with a link, and one with an iframe.
-    $this->addBlock('Search form', '#layout-builder .search-block-form');
+    $this->addBlock('Search form', '#layout-builder .block-search');
     $this->addBlock('Block with link', '#link-that-should-be-disabled');
     $this->addBlock('Block with iframe', '#iframe-that-should-be-disabled');
 
     // Ensure the links and forms are disabled using the defaults before the
     // layout is saved.
     $this->assertLinksFormIframeNotInteractive();
-
     $page->pressButton('Save layout');
     $this->clickLink('Manage layout');
 
