diff --git a/lib/client/client.c b/lib/client/client.c
index a4eb7a6ea0a1ab05aba08e9e629ed22e608486fb..bd6ce27aeeb72ab1f5e4d1c43adc2add2830b3be 100644
--- a/lib/client/client.c
+++ b/lib/client/client.c
@@ -868,6 +868,9 @@ check_extensions:
 	 * X <-> B
 	 * X <-> pAn <-> pB
 	 */
+
+	lws_vhost_lock(wsi->vhost);
+
 	wsi->same_vh_protocol_prev = /* guy who points to us */
 		&wsi->vhost->same_vh_protocol_list[n];
 	wsi->same_vh_protocol_next = /* old first guy is our next */
@@ -880,6 +883,8 @@ check_extensions:
 		wsi->same_vh_protocol_next->same_vh_protocol_prev =
 				&wsi->same_vh_protocol_next;
 
+	lws_vhost_unlock(wsi->vhost);
+
 #ifndef LWS_NO_EXTENSIONS
 	/* instantiate the accepted extensions */
 
diff --git a/lib/context.c b/lib/context.c
index f0cb8bab1620466e85a1b38419a9f43ee2b1d115..6bd4a8bda8ddac36ab4f8b62fa0297649d50a0bf 100644
--- a/lib/context.c
+++ b/lib/context.c
@@ -570,6 +570,10 @@ lws_create_vhost(struct lws_context *context,
 	if (!vh)
 		return NULL;
 
+#if LWS_MAX_SMP > 1
+	pthread_mutex_init(&vh->lock, NULL);
+#endif
+
 	if (!info->protocols)
 		info->protocols = &protocols_dummy[0];
 
@@ -1589,6 +1593,10 @@ lws_vhost_destroy2(struct lws_vhost *vh)
 
 	lws_free_set_NULL(vh->alloc_cert_path);
 
+#if LWS_MAX_SMP > 1
+       pthread_mutex_destroy(&vh->lock);
+#endif
+
 	/*
 	 * although async event callbacks may still come for wsi handles with
 	 * pending close in the case of asycn event library like libuv,
diff --git a/lib/pollfd.c b/lib/pollfd.c
index 8d63c46818eab026466690fc316c54d4f815a959..c08f20862349ab804c0517c2c429bccdb0be2f29 100644
--- a/lib/pollfd.c
+++ b/lib/pollfd.c
@@ -532,6 +532,8 @@ lws_same_vh_protocol_insert(struct lws *wsi, int n)
 		lwsl_notice("Attempted to attach wsi twice to same vh prot\n");
 	}
 
+	lws_vhost_lock(wsi->vhost);
+
 	wsi->same_vh_protocol_prev = &wsi->vhost->same_vh_protocol_list[n];
 	/* old first guy is our next */
 	wsi->same_vh_protocol_next =  wsi->vhost->same_vh_protocol_list[n];
@@ -542,6 +544,8 @@ lws_same_vh_protocol_insert(struct lws *wsi, int n)
 		/* old first guy points back to us now */
 		wsi->same_vh_protocol_next->same_vh_protocol_prev =
 				&wsi->same_vh_protocol_next;
+
+	lws_vhost_unlock(wsi->vhost);
 }
 
 void
@@ -556,6 +560,11 @@ lws_same_vh_protocol_remove(struct lws *wsi)
 	 */
 	lwsl_info("%s: removing same prot wsi %p\n", __func__, wsi);
 
+	if (!wsi->vhost)
+		return;
+
+	lws_vhost_lock(wsi->vhost);
+
 	if (wsi->same_vh_protocol_prev) {
 		assert (*(wsi->same_vh_protocol_prev) == wsi);
 		lwsl_info("have prev %p, setting him to our next %p\n",
@@ -574,6 +583,8 @@ lws_same_vh_protocol_remove(struct lws *wsi)
 
 	wsi->same_vh_protocol_prev = NULL;
 	wsi->same_vh_protocol_next = NULL;
+
+	lws_vhost_unlock(wsi->vhost);
 }
 
 
diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h
index 5b915793ae8df94dfbd6b86fb2f96c9af44e4f24..da5c15a7f2595307ee731e7339bf1bf1892907c9 100644
--- a/lib/private-libwebsockets.h
+++ b/lib/private-libwebsockets.h
@@ -928,6 +928,9 @@ struct lws_tls_ss_pieces;
 struct lws_vhost {
 	char http_proxy_address[128];
 	char proxy_basic_auth_token[128];
+#if LWS_MAX_SMP > 1
+	pthread_mutex_t lock;
+#endif
 #if defined(LWS_WITH_HTTP2)
 	struct http2_settings set;
 #endif
@@ -2480,6 +2483,19 @@ lws_context_unlock(struct lws_context *context)
 		pthread_mutex_unlock(&context->lock);
 }
 
+static LWS_INLINE void
+lws_vhost_lock(struct lws_vhost *vhost)
+{
+	pthread_mutex_lock(&vhost->lock);
+}
+
+static LWS_INLINE void
+lws_vhost_unlock(struct lws_vhost *vhost)
+{
+	pthread_mutex_unlock(&vhost->lock);
+}
+
+
 #else
 #define lws_pt_mutex_init(_a) (void)(_a)
 #define lws_pt_mutex_destroy(_a) (void)(_a)
@@ -2487,6 +2503,8 @@ lws_context_unlock(struct lws_context *context)
 #define lws_pt_unlock(_a) (void)(_a)
 #define lws_context_lock(_a) (void)(_a)
 #define lws_context_unlock(_a) (void)(_a)
+#define lws_vhost_lock(_a) (void)(_a)
+#define lws_vhost_unlock(_a) (void)(_a)
 #endif
 
 LWS_EXTERN int LWS_WARN_UNUSED_RESULT
diff --git a/lib/service.c b/lib/service.c
index 627b90d0651d3825e00155b79f22741d757a7b82..034d94d47847bab8efe937d22f4dc44d9d8e04b1 100644
--- a/lib/service.c
+++ b/lib/service.c
@@ -1281,6 +1281,9 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd,
 		context->last_ws_ping_pong_check_s = now;
 
 		while (vh) {
+
+			lws_vhost_lock(vh);
+
 			for (n = 0; n < vh->count_protocols; n++) {
 				wsi = vh->same_vh_protocol_list[n];
 
@@ -1306,6 +1309,9 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd,
 					wsi = wsi->same_vh_protocol_next;
 				}
 			}
+
+			lws_vhost_unlock(vh);
+
 			vh = vh->vhost_next;
 		}
 	}