More synchronized ideas

Michel Fortin michel.fortin at michelf.com
Mon Jun 4 10:40:38 PDT 2012


On 2012-06-04 13:15:57 +0000, "Jason House" <jason.james.house at gmail.com> said:

> The example about current D seems a bit lacking. You change behavior 
> because it's easy to code a different way. If you really want to use 
> synchronized classes, then you should have two of them. The map can be 
> in one synchronized class and the counters can be in another. the main 
> class in the example would simply call methods on the synchronized 
> objects.

Valid comment. I thought about creating yet another example 
illustrating that, but I gave up when realizing the silliness of it. I 
mean, yes you can make it work, but at the price of writing a lot of 
boilerplate code just for forwarding things around.

Here's a modified implementation of that dictionary class, wrapping the 
translations AA and the two counters in two distinct classes:

	class Dictionary
	{
	    private SynchronizedStringMap translations;
	    private SynchronizedCounters counters;
	
	    void addWord(string word, string foreignWord)
	    {
	        synchronized(translations)
	        {
	            translations[word] = foreignWord;
	
	            counters.addUnconfirmed();
	        }
	    }

	
	    bool confirmWord(string word, string foreignWord)
	    {
	        synchronized(translations)
	        {
	            string * found = word in translation;
	            if (!found)
	                return false;
	            if (*found != foreignWord)
	                return false;
	        }
	        synchronized(counters)
	        {
	            counters.removeUnconfirmed();
	            counters.addConfirmed();
	        }
	        globalNotifyWordConfirmed(word, foreignWord);
	        return true;
	    }
	}

That done, I still have to implement two other classes: 
SynchronizedStringMap which needs to implement the '[]' and 'in' 
operators, and counters which needs to implement addUnconfirmed, and 
SynchronizedCounters which needs to implement addUnconfirmed, 
removeUnconfirmed, and addConfirmed. All those functions just 
forwarding calls to the wrapped variable(s). And all this for a simple 
toy example.

That said, the other point is that it's too easy to shoot yourself in 
the foot using implicit synchronization. It's easy to forget you still 
have a mutex locked when adding the call to globalNotifyWordConfirmed, 
especially if you add this line of code later in the development 
process and you have forgotten about the "synchronized" keyword far 
away at the very top of the class declaration. And once you have a 
deadlock and you've identified the culprit, to fix the bug you need to 
split everything that needs to be synchronized into a separate class, a 
tiresome and bug-prone process, just because you can't opt-out of the 
implicit synchronization. Call me nuts if you want, but I think this is 
awful.


> That being said, I've never used synchronized classes in my 
> multithreaded D1/D2 code. I used Tango's Mutexes and Conditions. 
> They're more flexible.

I'd say it's a good choice. How does it work with shared variables in 
D2, or are you just ignoring the type system?


-- 
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/



More information about the Digitalmars-d mailing list