Shared, but synchronisation is not desired for multithreading

Alex Parrill via Digitalmars-d digitalmars-d at puremagic.com
Sat Jun 4 08:51:22 PDT 2016


On Saturday, 4 June 2016 at 15:11:51 UTC, tcak wrote:
> If you ignore the discouraged __gshared keyword, to be able to 
> share a variable between threads, you need to be using "shared" 
> keyword.
>
> While designing your class with "shared" methods, the compiler 
> directly assumes that objects of this class must be protected 
> against threading problems.
>
> There can be three USAGEs of a class object:
>
> 1. It will be non-shared. So, it is stored in TLS, and only one 
> thread can access it.
>
> 2. It will be shared. But programmer knows that the object is 
> designed as "shared" with the purpose of reading its value from 
> multiple threads.
>
> 3. It will be shared. But the object must be synchronised. 
> Because programmer knows that multiple threads will be reading 
> from and writing to object.
>
> Currently, in a normal coding environment (I am not talking 
> about using extra parameters, increasing complexity etc), 
> distinguishing between 2 and 3 does not seem like possible. You 
> prepare your shared class, and its methods are designed to be 
> either sycnhronised or not synchronised. There is no middle 
> point unless you define the same method with different names, 
> or use a flag like "bool run_this_method_synchronised_please".
>
> So, what I did is using UDA for this with the name @ThreadSafe. 
> e.g.
>
> @ThreadSafe auto myObject = new shared MyClass();
>
> In a method of the class, I make the declaration as following:
>
> public void foo() shared{
> 	static if( std.traits.hasUDA!( this, ThreadSafe ) ){
> 		// lock mutex
> 		scope(exit){
> 			// unlock mutex
> 		}
> 	}
>
> 	// do your normal operations
> }
>
> This way, if the object is desired to be doing synchronisation, 
> you only add an attribute to it.
>
> There are some small problems here, those are related to D's 
> implementation right now:
>
> 1. There is no standard way of saying @ThreadSafe. You are 
> supposed to be defining it. If language was to be defining a 
> standard attribute as @ThreadSafe, it could be used everywhere 
> for this purpose.
>
> 2. If a method is defined as shared, compiler immediately warns 
> the programmer to use core.atomic.atomicOp. If codes are 
> already being designed as thread-safe by the programmer, normal 
> variable operations could be used without any concern.
>
> 3. As far as I remember, there were some talks about 
> synchronized keyword not being used much. Maybe its usage could 
> be changed to support this @ThreadSafe system.

If the method is thread-safe, it should be marked as shared. 
Otherwise, it should not be shared. I think you're trying to mark 
functions that aren't actually thread safe but you call in a 
`synchronized` context as shared, when they should not be.

If you've made guarantees that the shared object you are 
modifying can only be accessed by one thread, you can cast it to 
unshared, and call its thread-unsafe methods (which are now 
safe). I think there were plans to get `synchronized` to do this 
for you, but it doesn't, which makes it fairly unwieldy.

(It also doesn't help that many "thread-safe" functions in D 
aren't marked as shared where they really ought to be, ex. all 
the functions in core.sync.mutex)


More information about the Digitalmars-d mailing list