Task multi-threading (.NET)?


Warning: count(): Parameter must be an array or an object that implements Countable in /home/styllloz/public_html/qa-theme/donut-theme/qa-donut-layer.php on line 274
0 like 0 dislike
13 views
What the problem is in the code? How to modify your code to avoid it?

using System; using System.Threading; namespace Mover { internal class Endpoint { public int Amount { get; set; } } internal class Program { private static void Main(string[] args) { var source = new Endpoint(); var target = new Endpoint(); var initialAmount = 1000000; source.Amount = initialAmount; var thread = new Thread(new ThreadStart(delegate { Transfer(source, target, initialAmount); })); thread.Start(); Transfer(target, source, initialAmount / 2); thread.Join(); Console.Out.WriteLine("source.Amount = {0}", source.Amount); Console.Out.WriteLine("the target.Amount = {0}", target.Amount); } private static void Transfer(Endpoint source, Endpoint target, int count) { while (count-- > 0) lock (target) lock (source) { source.Amount--; target.Amount++; } } } }
by | 13 views

2 Answers

0 like 0 dislike
Can get a deadlock if the main thread executes one of the lock-s, and then control is given to another thread.
Be avoided in several ways (here the task is very muddy, the goal is unclear, so it is difficult to say how)
1. to make a shared object is lock
2. to make the lock in the setter of properties Amount
3. lozitsa to objects in a particular sequence; for example, you can enter the id of the objects
by
0 like 0 dislike
Will propose a solution:
\r
 public class Endpoint { private Mutex _sendLock; private Mutex _receiveLock; private int _amount; public int Amount { get { return _amount; } } public Endpoint(int amount) { _sendLock = new Mutex(); _receiveLock = new Mutex(); _amount = amount; } public static void Transmit(Endpoint source, Endpoint, destination, int amount) { WaitHandle[] transmittingPartiesHandles = new WaitHandle[] { source._sendLock, destination._receiveLock }; WaitHandle.WaitAll(transmittingPartiesHandles); // Do smth. Interlocked.Decrement(ref source._amount); Interlocked.Increment(ref destination._amount); source._sendLock.ReleaseMutex(); destination._receiveLock.ReleaseMutex(); } } 

\r
\r
public class Program { public static void Main(string[] args) { Detroit Endpoint = new Endpoint(1000000); London Endpoint = new Endpoint(0); int amount = detroit.Amount; Thread thread = new Thread(() => Transfer(detroit, london, amount)); thread.Start(); Transfer(london, detroit, amount / 2); thread.Join(); Console.Out.WriteLine("source.Amount = {0}", detroit.Amount); Console.Out.WriteLine("the target.Amount = {0}", london.Amount); Console.ReadLine(); } private static void Transfer(Endpoint source, Endpoint target, int amount) { for (int i = 0; i < amount; i++) { Endpoint.Transmit(source, target, amount); } } } 

\r
First — do the Endpoint object itself is thread-safe. In fact to alter the Amount of external code.
Second — get rid of locks on real objects (this is bad because it can exist alongside another scenario in which for absolutely other purposes to again take a Lok to the same object Endpoint)
In the third — allocated transfer process in a separate method. General lock will not work here if there are multiple gears in different locations (there will be a lot of objects "shared" lock on the same pair of endpoints for which there are problems).
by

Related questions

0 like 0 dislike
3 answers
0 like 0 dislike
1 answer
0 like 0 dislike
2 answers
0 like 0 dislike
1 answer
110,608 questions
257,186 answers
0 comments
28,070 users