diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index c50f9c4bf6..96986ad954 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -338,18 +338,13 @@ AtAbort_Twophase(void)
 	 * resources held by the transaction yet.  In those cases, the in-memory
 	 * state can be wrong, but it's too late to back out.
 	 */
+	LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE);
 	if (!MyLockedGxact->valid)
-	{
 		RemoveGXact(MyLockedGxact);
-	}
 	else
-	{
-		LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE);
-
 		MyLockedGxact->locking_backend = InvalidBackendId;
+	LWLockRelease(TwoPhaseStateLock);
 
-		LWLockRelease(TwoPhaseStateLock);
-	}
 	MyLockedGxact = NULL;
 }
 
@@ -624,6 +619,8 @@ LockGXact(const char *gid, Oid user)
 /*
  * RemoveGXact
  *		Remove the prepared transaction from the shared memory array.
+ *		Caller needs to hold an exclusive lock on TwoPhaseStateLock as
+ *		data of TwoPhaseState gets updated.
  *
  * NB: caller should have already removed it from ProcArray
  */
@@ -632,8 +629,6 @@ RemoveGXact(GlobalTransaction gxact)
 {
 	int			i;
 
-	LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE);
-
 	for (i = 0; i < TwoPhaseState->numPrepXacts; i++)
 	{
 		if (gxact == TwoPhaseState->prepXacts[i])
@@ -646,8 +641,6 @@ RemoveGXact(GlobalTransaction gxact)
 			gxact->next = TwoPhaseState->freeGXacts;
 			TwoPhaseState->freeGXacts = gxact;
 
-			LWLockRelease(TwoPhaseStateLock);
-
 			return;
 		}
 	}
@@ -1506,7 +1499,9 @@ FinishPreparedTransaction(const char *gid, bool isCommit)
 	if (gxact->ondisk)
 		RemoveTwoPhaseFile(xid, true);
 
+	LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE);
 	RemoveGXact(gxact);
+	LWLockRelease(TwoPhaseStateLock);
 	MyLockedGxact = NULL;
 
 	pfree(buf);
@@ -1781,6 +1776,9 @@ restoreTwoPhaseData(void)
  * If xids_p and nxids_p are not NULL, pointer to a palloc'd array of all
  * top-level xids is stored in *xids_p. The number of entries in the array
  * is returned in *nxids_p.
+ *
+ * An exclusive lock on TwoPhaseStateLock is taken for the duration of the
+ * scan of TwoPhaseState data as its may be updated.
  */
 TransactionId
 PrescanPreparedTransactions(TransactionId **xids_p, int *nxids_p)
@@ -1792,7 +1790,7 @@ PrescanPreparedTransactions(TransactionId **xids_p, int *nxids_p)
 	int			allocsize = 0;
 	int			i;
 
-	LWLockAcquire(TwoPhaseStateLock, LW_SHARED);
+	LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE);
 	for (i = 0; i < TwoPhaseState->numPrepXacts; i++)
 	{
 		TransactionId xid;
@@ -1861,13 +1859,16 @@ PrescanPreparedTransactions(TransactionId **xids_p, int *nxids_p)
  * The lack of calls to SubTransSetParent() calls here is by design;
  * those calls are made by RecoverPreparedTransactions() at the end of recovery
  * for those xacts that need this.
+ *
+ * An exclusive lock on TwoPhaseStateLock is taken for the duration of the
+ * scan of TwoPhaseState data as it may get updated.
  */
 void
 StandbyRecoverPreparedTransactions(void)
 {
 	int			i;
 
-	LWLockAcquire(TwoPhaseStateLock, LW_SHARED);
+	LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE);
 	for (i = 0; i < TwoPhaseState->numPrepXacts; i++)
 	{
 		TransactionId xid;
@@ -2001,6 +2002,9 @@ RecoverPreparedTransactions(void)
  *
  * If setNextXid is true, set ShmemVariableCache->nextXid to the newest
  * value scanned.
+ *
+ * Caller needs to hold an exclusive lock on TwoPhaseStateLock as data
+ * of TwoPhaseState gets updated.
  */
 static char *
 ProcessTwoPhaseBuffer(TransactionId xid,
@@ -2361,6 +2365,9 @@ PrepareRedoAdd(char *buf, XLogRecPtr start_lsn, XLogRecPtr end_lsn)
  * Remove the corresponding gxact entry from TwoPhaseState. Also
  * remove the 2PC file if a prepared transaction was saved via
  * an earlier checkpoint.
+ *
+ * Caller needs to hold an exclusive lock on TwoPhaseStateLock as
+ * data of TwoPhaseState gets updated.
  */
 void
 PrepareRedoRemove(TransactionId xid, bool giveWarning)
@@ -2371,7 +2378,6 @@ PrepareRedoRemove(TransactionId xid, bool giveWarning)
 
 	Assert(RecoveryInProgress());
 
-	LWLockAcquire(TwoPhaseStateLock, LW_SHARED);
 	for (i = 0; i < TwoPhaseState->numPrepXacts; i++)
 	{
 		gxact = TwoPhaseState->prepXacts[i];
@@ -2383,7 +2389,6 @@ PrepareRedoRemove(TransactionId xid, bool giveWarning)
 			break;
 		}
 	}
-	LWLockRelease(TwoPhaseStateLock);
 
 	/*
 	 * Just leave if there is nothing, this is expected during WAL replay.
