多分、こんなんでいいはず。

先日書いた記事 - Singletonクラスのアクセスを簡単にマルチスレッド対応させたい - krustf の雑記 で書きましたけど、最終的に今書いてるライブラリに追加したものです。
MSVC10, boost1.44.0で動作確認しました。

#include <utility>
#include <boost/thread/mutex.hpp>

// マルチスレッド
// -------------------------------------------
template< class T >
class multi_thread_access
{
public:
	multi_thread_access( T* )
		: Lock_( SingletonMutex_ ) {};
	multi_thread_access( multi_thread_access&& other )
		: Lock_( std::move( other.Lock_ ) ) {};
	multi_thread_access()
		: Lock_() {};

private:
	boost::mutex::scoped_lock	Lock_;
	static boost::mutex		SingletonMutex_;
};

// class<T> の唯一の Mutex インスタンス
template< class T >
boost::mutex multi_thread_access<T>::SingletonMutex_;

// シングルスレッド
// -------------------------------------------
template< class T >
class single_thread_access
{
public:
	single_thread_access( T* )
	{};
	single_thread_access( single_thread_access&& )
	{};
	single_thread_access()
	{};
};

// シングルトンポインタ
// AccessPolicy default - multi_thread_access<T>
// -------------------------------------------
template< class T
        , template< class U > class AccessType=multi_thread_access
>
class singleton_ptr : private AccessType<T>
{
public:
	typedef typename T			value_type;
	typedef typename value_type *		pointer;
	typedef typename value_type const*	const_pointer;
	typedef typename value_type &		reference;
	typedef typename value_type const&	const_reference;

	singleton_ptr( pointer ptr )
		: Instance_( ptr )
		, AccessType<T>( ptr ) {};
	singleton_ptr( singleton_ptr&& other )
		: Instance_( other.Instance_ )
		, AccessType<T>( std::move( other ) ) { other.Instance_ = NULL; };
	singleton_ptr()
		: Instance_( NULL )
		, AccessType<T>() {};

	// 通常は -> でアクセスするのみ
	pointer		operator->()	   { return get(); };
	const_pointer	operator->() const { return get(); };

	// 参照を受け取る
	pointer		get()		   { return Instance_; };
	const_pointer	get()	     const { return Instance_; };

	// * でのアクセス
	reference       operator*()        { return *Instance_; };
	const_reference operator*()  const { return *Instance_; };

	// インスタンスポインタを保持しているか
	operator	bool()	     const { return Instance_ != NULL; };
 
private:
	// Singleton へのポインタ
	pointer		    Instance_;

	// copy が暗黙的に呼ばれないようにする
	singleton_ptr&	operator=( singleton_ptr& );
			        singleton_ptr( singleton_ptr& );
	// move はコンストラクタのみを許可
	singleton_ptr&  operator=( singleton_ptr&& );
};

デフォルトはマルチスレッド用のアクセスポリシを持つようになっていて、boost::mutexでアクセス制御します。
コンストラクタにはわざとexplicitをつけていません。
後は Singleton クラスのインスタンス取得関数の戻り値に singleton_ptr を使うだけです。

#include "singleton_ptr.h"
#include <vector>

// 適当なSingletonクラス
class hoge
{
public:
	typedef std::vector<int> value_type;

	value_type& get() { return DataList_; };

	// singleton_ptr<T>で返すインスタンス取得関数を作る
	typedef krustf::singleton_ptr<hoge> instance_type;
	static instance_type get_instance();

private:
	value_type	DataList_;

	hoge() : DataList_() {};
	hoge( const hoge& );
	hoge( hoge&& );
	hoge&  operator=(const hoge&);
	hoge&& operator=(const hoge&&);
};

// Singleton インスタンスのポインタを返却
hoge::instance_type hoge::get_instance()
{
	static hoge _Instance;
	return &_Instance;
}

#include <boost/thread.hpp>
#include <iostream>
#include <algorithm>

// スレッド用
// データを挿入
void func1()
{
	for( int i = 0 ; i < 30 ; ++i )
	{
		auto x = hoge::get_instance();
		x->get().push_back( i );
		boost::thread::sleep( boost::get_system_time() + boost::posix_time::milliseconds(1) );
	}
}

// データを変更
void func2()
{
	for( int i = 0 ; i < 40 ; ++i )
	{
		auto x = hoge::get_instance();
		std::for_each( x->get().begin()
			     , x->get().end()
			     , []( int& j ) { ++j; } );
		boost::thread::sleep( boost::get_system_time() + boost::posix_time::milliseconds(1) );
	}
}

int main()
{
	boost::thread_group	tgrp;

	tgrp.create_thread( &func1 );
	tgrp.create_thread( &func2 );
	tgrp.join_all();

	auto x = hoge::get_instance();

	std::for_each( x->get().begin()
		     , x->get().end()
		     , [] ( int i ) { std::cout << i << " "; } );
}

autoを使うことでかなり楽になります。
束縛している間に他のスレッドでget_instance()を呼び出すと、singleton_ptrコンストラクタでMutexがロック解除を待つのでしっかりスレッドの制御ができていると思います。
結果はこういう感じになるはずです。こればかりは実行環境によって結果が異なると思うのですが、値が壊れてなければ問題ないはずです。

40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69

問題点としては、自身のスレッドで既にsingleton_ptrインスタンスを取得していた場合、呼び出し順序の関係でロックが永遠に外れないので、完全に処理がフリーズします。
対処法としては他の関数を呼び出す際には既に所有しているsingleton_ptrの参照を引数とする、変数のスコープを意識する、など。

// 同一スレッドから呼び出す関数
void func( hoge::instance_type& x )
{
	/// x を使って何か処理
}

void hoge()
{
	auto x = hoge::get_instance();
	// x を使って何か処理
	func( x );
}

これだけを気をつければ、singleton_ptrを使って安全にマルチスレッド時の制御ができるだろうと睨んでいます。
シングルスレッド用のMutexロックをしないバージョンも用意しました。マルチスレッドで動かさない場合はこちらにしておいた方がいいでしょう。むしろMutexのロックの所為で処理時間を無駄に使います。