diff --git src/bp-messages/bp-messages-functions.php src/bp-messages/bp-messages-functions.php
index 83563350e..bd69e0680 100644
--- src/bp-messages/bp-messages-functions.php
+++ src/bp-messages/bp-messages-functions.php
@@ -324,12 +324,15 @@ function messages_check_thread_access( $thread_id, $user_id = 0 ) {
  *
  * Wrapper for {@link BP_Messages_Thread::mark_as_read()}.
  *
- * @param int $thread_id ID of the thread.
+ * @since 9.0.0 Added the `user_id` parameter.
+ *
+ * @param int $thread_id The message thread ID.
+ * @param int $user_id   Optional. The user the thread will be marked as read.
  *
  * @return false|int Number of threads marked as read or false on error.
  */
-function messages_mark_thread_read( $thread_id ) {
-	return BP_Messages_Thread::mark_as_read( $thread_id );
+function messages_mark_thread_read( $thread_id, $user_id = 0 ) {
+	return BP_Messages_Thread::mark_as_read( $thread_id, $user_id );
 }
 
 /**
@@ -337,12 +340,15 @@ function messages_mark_thread_read( $thread_id ) {
  *
  * Wrapper for {@link BP_Messages_Thread::mark_as_unread()}.
  *
- * @param int $thread_id ID of the thread.
+ * @since 9.0.0 Added the `user_id` parameter.
+ *
+ * @param int $thread_id The message thread ID.
+ * @param int $user_ud   Optional. The user the thread will be marked as unread.
  *
  * @return false|int Number of threads marked as unread or false on error.
  */
-function messages_mark_thread_unread( $thread_id ) {
-	return BP_Messages_Thread::mark_as_unread( $thread_id );
+function messages_mark_thread_unread( $thread_id, $user_id = 0 ) {
+	return BP_Messages_Thread::mark_as_unread( $thread_id, $user_id );
 }
 
 /**
diff --git src/bp-messages/classes/class-bp-messages-thread.php src/bp-messages/classes/class-bp-messages-thread.php
index 770e58434..8a87d8faa 100644
--- src/bp-messages/classes/class-bp-messages-thread.php
+++ src/bp-messages/classes/class-bp-messages-thread.php
@@ -612,18 +612,22 @@ class BP_Messages_Thread {
 	 * Mark a thread as read.
 	 *
 	 * @since 1.0.0
+	 * @since 9.0.0 Added the `user_id` parameter.
 	 *
 	 * @param int $thread_id The message thread ID.
+	 * @param int $user_id   The user the thread will be marked as read.
 	 *
 	 * @return false|int Number of threads marked as read or false on error.
 	 */
-	public static function mark_as_read( $thread_id = 0 ) {
+	public static function mark_as_read( $thread_id = 0, $user_id = 0 ) {
 		global $wpdb;
 
-		$user_id =
-			bp_displayed_user_id() ?
-			bp_displayed_user_id() :
-			bp_loggedin_user_id();
+		if ( empty( $user_id ) ) {
+			$user_id =
+				bp_displayed_user_id() ?
+				bp_displayed_user_id() :
+				bp_loggedin_user_id();
+		}
 
 		$bp     = buddypress();
 		$retval = $wpdb->query( $wpdb->prepare( "UPDATE {$bp->messages->table_name_recipients} SET unread_count = 0 WHERE user_id = %d AND thread_id = %d", $user_id, $thread_id ) );
@@ -635,10 +639,12 @@ class BP_Messages_Thread {
 		 * Fires when messages thread was marked as read.
 		 *
 		 * @since 2.8.0
+		 * @since 9.0.0 Added the `user_id` parameter.
 		 *
 		 * @param int $thread_id The message thread ID.
+		 * @param int $user_id   The user the thread will be marked as read.
 		 */
-		do_action( 'messages_thread_mark_as_read', $thread_id );
+		do_action( 'messages_thread_mark_as_read', $thread_id, $user_id );
 
 		return $retval;
 	}
@@ -647,18 +653,22 @@ class BP_Messages_Thread {
 	 * Mark a thread as unread.
 	 *
 	 * @since 1.0.0
+	 * @since 9.0.0 Added the `user_id` parameter.
 	 *
 	 * @param int $thread_id The message thread ID.
+	 * @param int $user_id   The user the thread will be marked as unread.
 	 *
 	 * @return false|int Number of threads marked as unread or false on error.
 	 */
-	public static function mark_as_unread( $thread_id = 0 ) {
+	public static function mark_as_unread( $thread_id = 0, $user_id = 0 ) {
 		global $wpdb;
 
-		$user_id =
-			bp_displayed_user_id() ?
-			bp_displayed_user_id() :
-			bp_loggedin_user_id();
+		if ( empty( $user_id ) ) {
+			$user_id =
+				bp_displayed_user_id() ?
+				bp_displayed_user_id() :
+				bp_loggedin_user_id();
+		}
 
 		$bp     = buddypress();
 		$retval = $wpdb->query( $wpdb->prepare( "UPDATE {$bp->messages->table_name_recipients} SET unread_count = 1 WHERE user_id = %d AND thread_id = %d", $user_id, $thread_id ) );
@@ -670,10 +680,12 @@ class BP_Messages_Thread {
 		 * Fires when messages thread was marked as unread.
 		 *
 		 * @since 2.8.0
+		 * @since 9.0.0 Added the `user_id` parameter.
 		 *
 		 * @param int $thread_id The message thread ID.
+		 * @param int $user_id   The user the thread will be marked as unread.
 		 */
-		do_action( 'messages_thread_mark_as_unread', $thread_id );
+		do_action( 'messages_thread_mark_as_unread', $thread_id, $user_id );
 
 		return $retval;
 	}
diff --git tests/phpunit/testcases/messages/class.bp-messages-thread.php tests/phpunit/testcases/messages/class.bp-messages-thread.php
index 3827997f0..f9de1d1cd 100644
--- tests/phpunit/testcases/messages/class.bp-messages-thread.php
+++ tests/phpunit/testcases/messages/class.bp-messages-thread.php
@@ -318,6 +318,65 @@ class BP_Tests_BP_Messages_Thread extends BP_UnitTestCase {
 		$this->set_current_user( $current_user );
 	}
 
+	/**
+	 * @group cache
+	 */
+	public function test_marking_a_thread_as_read_with_specific_user_id() {
+		$u1      = self::factory()->user->create();
+		$u2      = self::factory()->user->create();
+		$message = self::factory()->message->create_and_get( array(
+			'sender_id'  => $u1,
+			'recipients' => array( $u2 ),
+			'subject'    => 'Foo',
+		) );
+
+		$thread_id = $message->thread_id;
+
+		// Cache should be populated.
+		$this->assertTrue( (bool) wp_cache_get( 'thread_recipients_' . $thread_id, 'bp_messages' ) );
+
+		// Mark thread as read.
+		messages_mark_thread_read( $thread_id, $u2 );
+
+		// Cache should be empty.
+		$this->assertFalse( wp_cache_get( 'thread_recipients_' . $thread_id, 'bp_messages' ) );
+
+		$thread = new BP_Messages_Thread( $thread_id );
+
+		$this->assertFalse( (bool) $thread->unread_count );
+		$this->assertFalse( (bool) $thread->recipients[ $u1 ]->unread_count );
+		$this->assertFalse( (bool) $thread->recipients[ $u2 ]->unread_count );
+	}
+
+	/**
+	 * @group cache
+	 */
+	public function test_marking_a_thread_as_unread_with_specific_user_id() {
+		$u1      = self::factory()->user->create();
+		$u2      = self::factory()->user->create();
+		$message = self::factory()->message->create_and_get( array(
+			'sender_id'  => $u1,
+			'recipients' => array( $u2 ),
+			'subject'    => 'Foo',
+		) );
+
+		$thread_id = $message->thread_id;
+
+		// Cache should be populated.
+		$this->assertTrue( (bool) wp_cache_get( 'thread_recipients_' . $thread_id, 'bp_messages' ) );
+
+		// Mark thread as unread.
+		messages_mark_thread_unread( $thread_id, $u2 );
+
+		// Cache should be empty.
+		$this->assertFalse( wp_cache_get( 'thread_recipients_' . $thread_id, 'bp_messages' ) );
+
+		$thread = new BP_Messages_Thread( $thread_id );
+
+		$this->assertFalse( (bool) $thread->recipients[ $u1 ]->unread_count );
+		$this->assertTrue( (bool) $thread->recipients[ $u2 ]->unread_count );
+	}
+
 	/**
 	 * @group get_recipients
 	 * @group cache
