There was a need: to restrict access to the object (only one thread can use it). Ie only one stream can use methods and methods of its objects. Sample code (method call).
var human=new Human("Dima"); var ts=new Task(human.Coat("2").Sleeve.Right.Cut); ts.Start(); Ie I create a person with the name "Dima" and say: man, cut off the right sleeve of the second coat. Moreover, the Coat method refers to the Coats collection for a while, that is, Human has collections of empty Coats. When referring to this method, we pass the coat ID and continue to work with it. We send requests to the site.
The hitch is that all this will take place in a multi-thread, that is, I can call 4 similar methods and pull a random Coat from the array. If he is busy with some thread (for example, I called Cut ()), then he waits until the stream runs. After working out Coat is cleared (more precisely, the identifier) and ready to use.
I tried to make the lock operator on the Coat returned from the collection (in the form of a locker), but this is stupid, because it returns this object and doesn't care. I tried to create a flag, but in a multithreading garbage turned out. I tried a couple of ways, but I don’t remember them and they are as stupid as these.
I think to do so:
var human=new Human("Dima"); Coat coat; lock (coat=human.Coat("2")) { var ts=new Task(human.Coat("2").Sleeve.Right.Cut); ts.Start; } And further, when initializing objects (for example, the Sleeve), to transfer this coat and insert lock in each method, but it smacks it with a bicycle on a crutch, ... I feel that in theory I miss a very important point, but which one.
Question: how to do such a thing? Is it possible? Is my method suitable and how do you usually do this?
PS An example of an abstract, vital code can not show.
Update
Thinking on the method above, I realized that again it was not correct. If I set up lock (coat) everywhere, then ...
Initialize the variable Sleeve and pass Coat
_ sleeve=new Sleeve(this); Lock на этот Sleeve private SleeveClass _sleeve; public SleeveClass Sleeve { get { lock (this) { return _sleeve; } } } Same with Right
Cut method
public void Cut() { lock (_сoat) { Console.WriteLine(String.Format("Coat {0}",_сoat.CoatId)); } } It can happen like this: there are two streams, one waits somewhere on a change in Coat data. For example here: public CoatClass Coat (string CoatId) {
lock (CoatObj) { CoatClass CoatObj; _coatPull.TryPeek(out CoatObj); CoatObj.CoatId = CoatId; return CoatObj; } } And the other is in the Cut method. The Coat object may first change in one thread, give the signal "worked", and then the Cut will work and in the end we will cut off the wrong coat. Therefore, this option is not suitable, you need to continuously block access to objects and fields, it is busy with some kind of stream.
I use Concurrent collection. Yes, it is thread-safe, but the essence is different there (as far as I understood). A frequent problem when working with a collection in multithreading is the simultaneous recording and deletion of the same object. And this collection just gives access to only one thread, which solves this problem (and several others). Unlike the others, the collection produces a random element. Tobish all collections solve the problem of working with her, and not with the elements of the collection.