Index: src/wp-includes/post.php
===================================================================
--- src/wp-includes/post.php	(revision 37687)
+++ src/wp-includes/post.php	(working copy)
@@ -2169,7 +2169,18 @@
 	if ( ! in_array($post_id, $stickies) )
 		$stickies[] = $post_id;
 
-	update_option('sticky_posts', $stickies);
+	$updated = update_option( 'sticky_posts', $stickies );
+
+	if ( $updated ) {
+		/**
+		 * Fires once a post has been added to the sticky list.
+		 *
+		 * @since 4.6.0
+		 *
+		 * @param int $post_id ID of the post that was stuck.
+		 */
+		do_action( 'post_stuck', $post_id );
+	}
 }
 
 /**
@@ -2196,7 +2207,18 @@
 
 	array_splice($stickies, $offset, 1);
 
-	update_option('sticky_posts', $stickies);
+	$updated = update_option( 'sticky_posts', $stickies );
+
+	if ( $updated ) {
+		/**
+		 * Fires once a post has been removed from the sticky list.
+		 *
+		 * @since 4.6.0
+		 *
+		 * @param int $post_id ID of the post that was unstuck.
+		 */
+		do_action( 'post_unstuck', $post_id );
+	}
 }
 
 /**
Index: tests/phpunit/tests/post.php
===================================================================
--- tests/phpunit/tests/post.php	(revision 37687)
+++ tests/phpunit/tests/post.php	(working copy)
@@ -1182,6 +1182,33 @@
 	}
 
 	/**
+	 * Test that hooks are fired when post gets stuck and unstuck.
+	 *
+	 * @ticket 35600
+	 */
+	function test_hooks_fire_when_post_gets_stuck_and_unstuck() {
+		$post_id = self::factory()->post->create();
+		$a1 = new MockAction();
+		$a2 = new MockAction();
+
+		$this->assertFalse( is_sticky( $post_id ) );
+
+		add_action( 'post_stuck', array( $a1, 'action' ) );
+		add_action( 'post_unstuck', array( $a2, 'action' ) );
+
+		stick_post( $post_id );
+		$this->assertTrue( is_sticky( $post_id ) );
+		unstick_post( $post_id );
+		$this->assertFalse( is_sticky( $post_id ) );
+
+		remove_action( 'post_stuck', array( $a1, 'action' ) );
+		remove_action( 'post_unstuck', array( $a2, 'action' ) );
+
+		$this->assertEquals( 1, $a1->get_call_count() );
+		$this->assertEquals( 1, $a2->get_call_count() );
+	}
+
+	/**
 	 * If a post is updated without providing a post_name param,
 	 * a new slug should not be generated.
 	 *
