diff --git a/Makefile.am b/Makefile.am
index eaba44331..0e76eb54f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -172,6 +172,8 @@ src_mpd_SOURCES = \
 	$(DECODER_SRC) \
 	$(OUTPUT_API_SRC) \
 	$(MIXER_API_SRC) \
+	src/thread/Mutex.hxx \
+	src/thread/CriticalSection.hxx \
 	src/glib_socket.h \
 	src/clock.c src/clock.h \
 	src/notify.c \
diff --git a/src/MusicBuffer.cxx b/src/MusicBuffer.cxx
index 5fddddc22..ea03fc0b9 100644
--- a/src/MusicBuffer.cxx
+++ b/src/MusicBuffer.cxx
@@ -20,27 +20,21 @@
 #include "config.h"
 #include "MusicBuffer.hxx"
 #include "MusicChunk.hxx"
+#include "thread/Mutex.hxx"
 #include "util/SliceBuffer.hxx"
 #include "mpd_error.h"
 
-#include <glib.h>
-
 #include <assert.h>
 
 struct music_buffer : public SliceBuffer<music_chunk>  {
 	/** a mutex which protects #available */
-	GMutex *mutex;
+	Mutex mutex;
 
 	music_buffer(unsigned num_chunks)
-		:SliceBuffer(num_chunks),
-		 mutex(g_mutex_new()) {
+		:SliceBuffer(num_chunks) {
 		if (IsOOM())
 			MPD_ERROR("Failed to allocate buffer");
 	}
-
-	~music_buffer() {
-		g_mutex_free(mutex);
-	}
 };
 
 struct music_buffer *
@@ -64,10 +58,8 @@ music_buffer_size(const struct music_buffer *buffer)
 struct music_chunk *
 music_buffer_allocate(struct music_buffer *buffer)
 {
-	g_mutex_lock(buffer->mutex);
-	struct music_chunk *chunk = buffer->Allocate();
-	g_mutex_unlock(buffer->mutex);
-	return chunk;
+	const ScopeLock protect(buffer->mutex);
+	return buffer->Allocate();
 }
 
 void
@@ -76,7 +68,7 @@ music_buffer_return(struct music_buffer *buffer, struct music_chunk *chunk)
 	assert(buffer != NULL);
 	assert(chunk != NULL);
 
-	g_mutex_lock(buffer->mutex);
+	const ScopeLock protect(buffer->mutex);
 
 	if (chunk->other != nullptr) {
 		assert(chunk->other->other == nullptr);
@@ -84,6 +76,4 @@ music_buffer_return(struct music_buffer *buffer, struct music_chunk *chunk)
 	}
 
 	buffer->Free(chunk);
-
-	g_mutex_unlock(buffer->mutex);
 }
diff --git a/src/MusicPipe.cxx b/src/MusicPipe.cxx
index 38c3af776..010da97ba 100644
--- a/src/MusicPipe.cxx
+++ b/src/MusicPipe.cxx
@@ -21,6 +21,7 @@
 #include "MusicPipe.hxx"
 #include "MusicBuffer.hxx"
 #include "MusicChunk.hxx"
+#include "thread/Mutex.hxx"
 
 #include <glib.h>
 
@@ -37,16 +38,14 @@ struct music_pipe {
 	unsigned size;
 
 	/** a mutex which protects #head and #tail_r */
-	GMutex *mutex;
+	mutable Mutex mutex;
 
 #ifndef NDEBUG
 	struct audio_format audio_format;
 #endif
 
 	music_pipe()
-		:head(nullptr), tail_r(&head),
-		 size(0),
-		 mutex(g_mutex_new()) {
+		:head(nullptr), tail_r(&head), size(0) {
 #ifndef NDEBUG
 		audio_format_clear(&audio_format);
 #endif
@@ -55,8 +54,6 @@ struct music_pipe {
 	~music_pipe() {
 		assert(head == nullptr);
 		assert(tail_r == &head);
-
-		g_mutex_free(mutex);
 	}
 };
 
@@ -89,17 +86,12 @@ bool
 music_pipe_contains(const struct music_pipe *mp,
 		    const struct music_chunk *chunk)
 {
-	g_mutex_lock(mp->mutex);
+	const ScopeLock protect(mp->mutex);
 
 	for (const struct music_chunk *i = mp->head;
-	     i != NULL; i = i->next) {
-		if (i == chunk) {
-			g_mutex_unlock(mp->mutex);
+	     i != NULL; i = i->next)
+		if (i == chunk)
 			return true;
-		}
-	}
-
-	g_mutex_unlock(mp->mutex);
 
 	return false;
 }
@@ -115,11 +107,9 @@ music_pipe_peek(const struct music_pipe *mp)
 struct music_chunk *
 music_pipe_shift(struct music_pipe *mp)
 {
-	struct music_chunk *chunk;
+	const ScopeLock protect(mp->mutex);
 
-	g_mutex_lock(mp->mutex);
-
-	chunk = mp->head;
+	struct music_chunk *chunk = mp->head;
 	if (chunk != NULL) {
 		assert(!music_chunk_is_empty(chunk));
 
@@ -145,8 +135,6 @@ music_pipe_shift(struct music_pipe *mp)
 #endif
 	}
 
-	g_mutex_unlock(mp->mutex);
-
 	return chunk;
 }
 
@@ -165,7 +153,7 @@ music_pipe_push(struct music_pipe *mp, struct music_chunk *chunk)
 	assert(!music_chunk_is_empty(chunk));
 	assert(chunk->length == 0 || audio_format_valid(&chunk->audio_format));
 
-	g_mutex_lock(mp->mutex);
+	const ScopeLock protect(mp->mutex);
 
 	assert(mp->size > 0 || !audio_format_defined(&mp->audio_format));
 	assert(!audio_format_defined(&mp->audio_format) ||
@@ -181,15 +169,11 @@ music_pipe_push(struct music_pipe *mp, struct music_chunk *chunk)
 	mp->tail_r = &chunk->next;
 
 	++mp->size;
-
-	g_mutex_unlock(mp->mutex);
 }
 
 unsigned
 music_pipe_size(const struct music_pipe *mp)
 {
-	g_mutex_lock(mp->mutex);
-	unsigned size = mp->size;
-	g_mutex_unlock(mp->mutex);
-	return size;
+	const ScopeLock protect(mp->mutex);
+	return mp->size;
 }
diff --git a/src/thread/CriticalSection.hxx b/src/thread/CriticalSection.hxx
new file mode 100644
index 000000000..f3faee943
--- /dev/null
+++ b/src/thread/CriticalSection.hxx
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2009-2013 Max Kellermann <max@duempel.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MPD_THREAD_CRITICAL_SECTION_HXX
+#define MPD_THREAD_CRITICAL_SECTION_HXX
+
+#include <windows.h>
+
+class CriticalSection {
+	CRITICAL_SECTION critical_section;
+
+public:
+	CriticalSection() {
+		::InitializeCriticalSection(&critical_section);
+	}
+
+	~CriticalSection() {
+		::DeleteCriticalSection(&critical_section);
+	}
+
+	CriticalSection(const CriticalSection &other) = delete;
+	CriticalSection &operator=(const CriticalSection &other) = delete;
+
+	void lock() {
+		::EnterCriticalSection(&critical_section);
+	};
+
+	bool try_lock() {
+		return ::TryEnterCriticalSection(&critical_section) != 0;
+	};
+
+	void unlock() {
+		::LeaveCriticalSection(&critical_section);
+	}
+};
+
+#endif
diff --git a/src/thread/Mutex.hxx b/src/thread/Mutex.hxx
new file mode 100644
index 000000000..df8d140c6
--- /dev/null
+++ b/src/thread/Mutex.hxx
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_THREAD_MUTEX_HXX
+#define MPD_THREAD_MUTEX_HXX
+
+#ifdef WIN32
+
+/* mingw-w64 4.6.3 lacks a std::mutex implementation */
+
+#include "CriticalSection.hxx"
+typedef CriticalSection Mutex;
+
+class ScopeLock {
+	Mutex &mutex;
+
+public:
+	ScopeLock(Mutex &_mutex):mutex(_mutex) {
+		mutex.lock();
+	};
+
+	~ScopeLock() {
+		mutex.unlock();
+	};
+
+	ScopeLock(const ScopeLock &other) = delete;
+	ScopeLock &operator=(const ScopeLock &other) = delete;
+};
+
+#else
+
+#include <mutex>
+typedef std::mutex Mutex;
+typedef std::lock_guard<std::mutex> ScopeLock;
+
+#endif
+
+#endif