diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c
index 4f446aa..7d60f31 100644
--- a/src/backend/storage/ipc/sinvaladt.c
+++ b/src/backend/storage/ipc/sinvaladt.c
@@ -499,11 +499,31 @@ SIGetDataEntries(SharedInvalidationMessage *data, int datasize)
 	int			max;
 	int			n;
 
-	LWLockAcquire(SInvalReadLock, LW_SHARED);
-
 	segP = shmInvalBuffer;
 	stateP = &segP->procState[MyBackendId - 1];
 
+	/*
+	 * Before starting to take locks, do a quick, unlocked test to see whether
+	 * there can possibly be anything to read.  On a multiprocessor system,
+	 * it's possible these loads could migrate backwards and occur before we
+	 * actually enter this function, so we might miss a sinval message that
+	 * was just added by some other processor.  But they can't migrate
+	 * backwards over a preceding lock acquisition, so it should be OK.  If
+	 * we haven't acquired a lock preventing against further relevant
+	 * invalidations, any such occurrence is not much different than if the
+	 * invalidation had arrived slightly later in the first place.
+	 *
+	 * It's important that we don't use the value read here to actually
+	 * read from the queue.  On machines with weak memory ordering, the
+	 * maxMsgNum bump could become visible before the queue entries themselves.
+	 * But the locking below will take care of that before rereading the
+	 * value.
+	 */
+	if (stateP->nextMsgNum == segP->maxMsgNum && !stateP->resetState)
+		return 0;
+
+	LWLockAcquire(SInvalReadLock, LW_SHARED);
+
 	/* Fetch current value of maxMsgNum using spinlock */
 	{
 		/* use volatile pointer to prevent code rearrangement */
