diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index 5184874064..385cb18644 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -774,8 +774,12 @@ void GfxPalette::saveLoadWithSerializer(Common::Serializer &s) {
 			s.syncAsSint16LE(_palVaryDirection);
 			s.syncAsUint16LE(_palVaryTicks);
 			s.syncAsSint32LE(_palVaryPaused);
-			if (s.getVersion() >= 40)
-				s.syncAsSint32LE(_palVarySignal);
+			if (s.getVersion() >= 40) {
+				int sig = _palVarySignal.get();
+				s.syncAsSint32LE(sig);
+				if (s.isLoading())
+					_palVarySignal = sig;
+			}
 		}
 
 		if (s.isLoading() && s.getVersion() < 40) {
diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp
index 6fe1fb1b49..129d93905e 100644
--- a/engines/sci/graphics/palette.cpp
+++ b/engines/sci/graphics/palette.cpp
@@ -848,21 +848,15 @@ void GfxPalette::kernelPalVaryDeinit() {
 }
 
 void GfxPalette::palVaryCallback(void *refCon) {
-	((GfxPalette *)refCon)->palVaryIncreaseSignal();
-}
-
-void GfxPalette::palVaryIncreaseSignal() {
-	// FIXME: increments from another thread aren't guaranteed to be atomic
-	if (!_palVaryPaused)
-		_palVarySignal++;
+	GfxPalette *pal = ((GfxPalette *)refCon);
+	if (!pal->_palVaryPaused)
+		pal->_palVarySignal++;
 }
 
 // Actually do the pal vary processing
 void GfxPalette::palVaryUpdate() {
-	if (_palVarySignal) {
-		palVaryProcess(_palVarySignal, true);
-		_palVarySignal = 0;
-	}
+	if (_palVarySignal.nonZero())
+		palVaryProcess(_palVarySignal.getAndZero(), true);
 }
 
 void GfxPalette::palVaryPrepareForTransition() {
diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h
index 2178de8a91..6e051ba40b 100644
--- a/engines/sci/graphics/palette.h
+++ b/engines/sci/graphics/palette.h
@@ -25,6 +25,7 @@
 
 #include "common/array.h"
 #include "sci/graphics/helpers.h"
+#include "sci/util.h"
 
 namespace Sci {
 
@@ -101,7 +102,6 @@ protected:
 	void palVaryRemoveTimer();
 	bool palVaryLoadTargetPalette(GuiResourceId resourceId);
 	static void palVaryCallback(void *refCon);
-	void palVaryIncreaseSignal();
 
 	GfxScreen *_screen;
 	ResourceManager *_resMan;
@@ -120,7 +120,7 @@ protected:
 	int16 _palVaryDirection;
 	uint16 _palVaryTicks;
 	int _palVaryPaused;
-	int _palVarySignal;
+	AtomicCounter _palVarySignal;
 	uint16 _totalScreenColors;
 
 	void loadMacIconBarPalette();
diff --git a/engines/sci/util.h b/engines/sci/util.h
index b0fee5151e..73625e5d31 100644
--- a/engines/sci/util.h
+++ b/engines/sci/util.h
@@ -24,6 +24,7 @@
 #define SCI_UTIL_H
 
 #include "common/scummsys.h"
+#include "common/mutex.h"
 
 namespace Sci {
 
@@ -45,6 +46,52 @@ void WRITE_SCI11ENDIAN_UINT32(void *ptr, uint32 val);
 // LE in SCI1.1 Mac, but BE in SCI32 Mac
 uint16 READ_SCI32ENDIAN_UINT16(const void *ptr);
 
+
+class AtomicCounter {
+public:
+	AtomicCounter() : _value(0) { }
+	AtomicCounter(int value) : _value(value) { }
+
+	int operator++() {
+		Common::StackLock l(_mutex);
+		return _value++;
+	}
+	int operator--() {
+		Common::StackLock l(_mutex);
+		return _value--;
+	}
+	int operator++(int) {
+		Common::StackLock l(_mutex);
+		return ++_value;
+	}
+	int operator--(int) {
+		Common::StackLock l(_mutex);
+		return --_value;
+	}
+	int operator=(int value) {
+		Common::StackLock l(_mutex);
+		return _value = value;
+	}
+	int get() const {
+		Common::StackLock l(_mutex);
+		return _value;
+	}
+	int getAndZero() {
+		Common::StackLock l(_mutex);
+		int v = _value;
+		_value = 0;
+		return v;
+	}
+	bool nonZero() const {
+		return _value != 0;
+	}
+
+protected:
+	Common::Mutex _mutex;
+	int _value;
+};
+
+
 } // End of namespace Sci
 
 #endif
