I think I am missing something obvious here:
Why does this code doesn't cause deadlock:
static void Main(string[] args)
{
object _lock1 = new object();
object _lock2 = new object();
Thread code1 = new Thread(() =>
{
lock (_lock1)
{
lock (_lock2)
{
Console.WriteLine("A");
Thread.Sleep(3000);
}
}
});
Thread code2 = new Thread(() =>
{
lock (_lock2)
{
lock (_lock1)
{
Console.WriteLine("B");
Thread.Sleep(3000);
}
}
});
code1.Start();
code2.Start();
code1.Join();
code2.Join();
Console.WriteLine("Done");
}
But this one does:
static void Main(string[] args)
{
object _lock1 = new object();
object _lock2 = new object();
Thread code1 = new Thread(() =>
{
lock (_lock1)
{
lock (_lock2)
{
Thread.Sleep(3000);
Console.WriteLine("A");
}
}
});
Thread code2 = new Thread(() =>
{
lock (_lock2)
{
Thread.Sleep(3000);
lock (_lock1)
{
Console.WriteLine("B");
}
}
});
code1.Start();
code2.Start();
code1.Join();
code2.Join();
Console.WriteLine("Done");
}
Both code snippets can cause deadlocks and should be avoided. It is just a coincidence, that first snippet didn't get into deadlock. Adding some operation between locks increases probability to get dead lock.
For example, if you add Console.Writeline in between lock1 and lock2 it also increases probability of the deadlock.
You can run your first snippet in loop and receive a deadlock. For example, this code get into deadlock after a while:
static void Main(string[] args)
{
for (int i = 0; i < 1000; i++)
{
object _lock1 = new object();
object _lock2 = new object();
Thread code1 = new Thread(() =>
{
lock (_lock1)
{
lock (_lock2)
{
Console.WriteLine("A");
Thread.Sleep(100);
}
}
});
Thread code2 = new Thread(() =>
{
lock (_lock2)
{
lock (_lock1)
{
Console.WriteLine("B");
Thread.Sleep(100);
}
}
});
code1.Start();
code2.Start();
code1.Join();
code2.Join();
}
Console.WriteLine("Done");
}
Regular Flow "assuming" Thread 1 executes first (this can actually still deadlock if t2 happens to catch l2 before t1):
t1 acquires l1
t1 acquires l2 //before t2..
t1 unlocks l2
t1 unlocks l1
t2 acquires l2
t2 sleeps
t2 acquires l1
t2 unlocks l1
t2 unlocks l2
If t2 "happens to run first"..
t2 acquires l2
t2 sleeps
t1 acquires l1 (while t2 is still sleeping)
t1 tries to acquire l2 but blocks.. it's already acquired by t2..
t2 is finished sleeping..
t2 tries to acquire l1 but blocks.. it's already acquired by t1..
IE: You can debug and see it print like:
Start T2
T2 - Locked L2
T2 - Sleeping
Start T1
T1 - Locked L1
-- DeadLock.. Neither can continue unless the other unlocks..
It's undefined behaviour. You also shouldn't be guessing which thread runs first.
To help explain the "deadlock" question -
Use Thread.Sleep if you really want to suspend the thread.
But in this case where you don't want to suspend the thread, just suspend the 'task'.
Use some like this:
await Task.Delay(myDuration);
This will not suspend the entire thread, but just the single task you want to suspend.
All other tasks on the same thread can continue running...
Related
I have three threads which are supposed to add a random int to a queue, a fourth that dequeues an int, and a fifth that prints the numbers within it. I'm using threads because they will eventually be needed for the scope of this program and to enqueue/dequeue far more numbers, but having issues with generating a random int. I'm using a class RandomGenerator to create the number, and creating an instance of this class then invoking its GetRandom method to set an int field to a random number. I'm then passing this field into the first three threads which invoke the method to enqueue. The int that prints is not random and I realize this is because I'm simply calling the method at the beginning of the program and passing the same exact number to all three threads. I'm relatively new to C# and realize I may be making a basic mistake. I also realize the fourth thread sometimes accesses the queue when it's empty but isn't as important at the moment. I have tried a number of different things with this and could also have the number generator in the Program class. Here is the code:
...
class Program
{
static void Main()
{
Program p = new Program();
RandomGenerator rg = new RandomGenerator();
Queue<int> numberQueue = new Queue<int>();
int randomNumber = rg.GetRandom(1, 10);
Thread T1 = new Thread(delegate () { p.EnqueueNumber(numberQueue, randomNumber); });
Thread T2 = new Thread(delegate () { p.EnqueueNumber(numberQueue, randomNumber); });
Thread T3 = new Thread(delegate () { p.EnqueueNumber(numberQueue, randomNumber); });
Thread T4 = new Thread(delegate () { p.DequeueNumber(numberQueue); });
Thread T5 = new Thread(delegate () { p.PrintNumbers(numberQueue); });
T1.Start();
T2.Start();
T3.Start();
T4.Start();
T5.Start();
T1.Join();
T2.Join();
T3.Join();
T4.Join();
T5.Join();
}
public void EnqueueNumber(Queue<int> numberQueue, int randomNumber)
{
numberQueue.Enqueue(randomNumber);
}
public void DequeueNumber(Queue<int> numberQueue)
{
numberQueue.Dequeue();
}
public void PrintNumbers(Queue<int> numberQueue)
{
foreach (int i in numberQueue)
{
Console.Write(i);
}
Console.ReadKey();
}
}
public class RandomGenerator
{
private static Random _random = new Random();
private static object syncLock = new object();
public int GetRandom(int min, int max)
{
lock (syncLock)
{
return _random.Next(min, max);
}
}
}
...
You are passing the return value of the GetRandom() method of your single RandomGenerator instance to each of the threads.
You need to pass a reference to the RandomGenerator to each of the threads instead, so GetRandom() can be called each time.
Thread T1 = new Thread(delegate () { p.EnqueueNumber(numberQueue, rg); });
If you create a RandomGenerator per thread you can also stop using locks which are overkill for this use case.
Finally if you insist on concurrent multi-write to, single-read from the same queue, you should also look at ConcurrentQueue rather than Queue as it is thread-safe.
Is there any way that I mimic in an short simple illustrative example of concurrent threads, that 2 threads can start the same method at the same time, and the processing is mixed between the two?
In the below example, I want to see sth like:
1 thread1
1 thread2
2 thread1
2 thread2
..
10 thread1
10 thread2
Instead, I get something like:
1 thread1
2 thread1
...
10 thread1
1 thread2
2 thread2
...
10 thread2
Be kind, I'm just starting to learn threads.
In short, I want to simulate the effect of the two threads starting at exactly the same time, not one immediately after the other.
After I achieve the above mentioned, I want to use the lock in order for thread1 to completely finish executing before starting thread2. This already happens in my example even before employing lock.
using System;
using System.Threading;
public class Program
{
public class C1
{
private object obj = new object();
public void Ten()
{
//lock(obj)
//{
for(int i=1; i<=10; i++)
{
Console.WriteLine(i + " " + Thread.CurrentThread.Name);
}
//}
}
}
public static void Main()
{
Thread t1 = new Thread(new ThreadStart(new C1().Ten));
Thread t2 = new Thread(new ThreadStart(new C1().Ten));
t1.Name = "thread1";
t2.Name = "thread2";
t1.Start();
t2.Start();
}
}
as ESG mentioned in the comment, the code runs too fast. That's why you are not getting expected output. Try adding some sleep inside the loop to get the expected result.
using System;
using System.Threading;
public class Program
{
public class C1
{
private static object obj = new object();
public void Ten()
{
//lock(obj)
//{
for(int i=1; i<=10; i++)
{
Console.WriteLine(i + " " + Thread.CurrentThread.Name);
Thread.Sleep(1000); //<-- add sleep
}
//}
}
}
public static void Main()
{
Thread t1 = new Thread(new ThreadStart(new C1().Ten));
Thread t2 = new Thread(new ThreadStart(new C1().Ten));
t1.Name = "thread1";
t2.Name = "thread2";
t1.Start();
t2.Start();
}
}
On the second note about locking the resource so that thread2 should wait for thread1 to complete. You will need to mark the obj as static variable.
Hope it helps.
If I have fire 3 threads. Is it possible to know which thread completed first.
Some sample code
Thread thread1 = new Thread(() => MyFunc());
Thread thread2 = new Thread(() => MyFunc());
Thread thread3 = new Thread(() => MyFunc());
thread1.Start();
thread2.Start();
thread3.Start();
while (thread1.IsAlive || thread2.IsAlive || thread3.IsAlive)
{
//I need condition to which thread dead first.
}
You can use Interlocked.CompareExchange to set the winning thread:
static Thread winner = null;
private static void MyFunc()
{
Thread.Sleep((int)(new Random().NextDouble() * 1000));
Interlocked.CompareExchange(ref winner, Thread.CurrentThread, null);
}
public static void Main()
{
Thread thread1 = new Thread(() => MyFunc());
Thread thread2 = new Thread(() => MyFunc());
Thread thread3 = new Thread(() => MyFunc());
thread1.Name = "thread1";
thread2.Name = "thread2";
thread3.Name = "thread3";
thread1.Start();
thread2.Start();
thread3.Start();
thread1.Join();
thread2.Join();
thread3.Join();
Console.WriteLine("The winner is {0}", winner.Name);
}
Live Demo
UPDATE: If you don't want all threads to finish before you check, there is an easier method using AutoResetEvents and WaitHandle.WaitAny():
private static void MyFunc(AutoResetEvent ev)
{
Thread.Sleep((int)(new Random().NextDouble() * 1000));
ev.Set();
}
public static void Main()
{
AutoResetEvent[] evs = {new AutoResetEvent(false), new AutoResetEvent(false), new AutoResetEvent(false)};
Thread thread1 = new Thread(() => MyFunc(evs[0]));
Thread thread2 = new Thread(() => MyFunc(evs[1]));
Thread thread3 = new Thread(() => MyFunc(evs[2]));
thread1.Start();
thread2.Start();
thread3.Start();
int winner = WaitHandle.WaitAny(evs);
Console.WriteLine("The winner is thread{0}", winner + 1);
}
Live Demo
one simple workaround would be that you write the thread name to a list or something when it completes?
All threads can have an arbitrary delay after the last instruction of your code is completed. After the last instruction has run the OS still has some work to do. It can take an arbitrarily long time.
For that reason it is never meaningful to find out what thread completed first. This is the XY-Problem. This question is meaningless. Its answer will not help you accomplish anything. Ask a new question with the real problem.
You probably want to tell which one of multiple side-effects happened first. Even if they completed in order A, B the threads they ran on can complete in any order. The thread order tells you nothing.
I have three threads in my program and I want that when thread one finishes it signals thread 2 to start and when thread 2 finishes it should signal thread 3 to start.
How can I achieve this, I know there are wait handles to do that in C#, but I don't know how to use them ?
Following is the code of my program:
class Program
{
static void Main(string[] args)
{
Thread t1 = new Thread(Task1);
Thread t2 = new Thread(Task2);
Thread t3 = new Thread(Task3);
t1.Start();
t2.Start();
t3.Start();
Console.Read();
}
public static void Task1()
{
Console.WriteLine("I am assigned task 1:");
for (int i = 0; i < 50; i++)
{
Console.WriteLine("Task1" );
}
}
public static void Task2()
{
Console.WriteLine("I am assigned task 2:");
for (int i = 0; i < 50; i++)
{
Console.WriteLine("Task2");
}
}
public static void Task3()
{
Console.WriteLine("I am assigned task 3:");
for (int i = 0; i < 50; i++)
{
Console.WriteLine("Task3");
}
}
}
You need to pass events into the threaded functions that indicate what to signal when each one has finished and what to wait on before they run. Take a look at the (untested) code below to see what I mean:
class Program
{
static void Main(string[] args)
{
Thread t1 = new Thread(Task1);
ManualResetEvent e1=new ManualResetEvent(false);
Thread t2 = new Thread(Task2);
ManualResetEvent e2=new ManualResetEvent(false);
Thread t3 = new Thread(Task3);
ManualResetEvent e3=new ManualResetEvent(false);
t1.Start(()=>Task1(e1));
t2.Start(()=>Task2(e1,e2));
t3.Start(()=>Task3(e2,e3);
Console.Read();
t1.Join();
t2.Join();
t3.Join();
}
public static void Task1(EventWaitHandle handle)
{
Console.WriteLine("I am assigned task 1:");
for (int i = 0; i < 50; i++)
{
Console.WriteLine("Task1" );
}
handle.Set();
}
public static void Task2(EventWaitHandle waitFor, EventWaitHandle handle)
{
waitFor.WaitOne();
Console.WriteLine("I am assigned task 2:");
for (int i = 0; i < 50; i++)
{
Console.WriteLine("Task2");
}
handle.Set();
}
public static void Task3(EventWaitHandle waitFor, EventWaitHandle handle)
{
waitFor.WaitOne();
Console.WriteLine("I am assigned task 3:");
for (int i = 0; i < 50; i++)
{
Console.WriteLine("Task3");
}
handle.Set();
}
}
It appears that you want to run Tasks 1 - 3 to execute synchronously. So, you might as well do:
Task1();
Task2();
Task3();
If you want to offload the execution of these tasks to another thread, you can do:
static void RunTasks()
{
Task1();
Task2();
Task3();
}
static void Main()
{
new Thread(RunTasks).Start();
}
If you really wanted each task to run on a separate thread, and wait for the previous task to finish, you can use the Thread.Join method.
EDIT:
Since you really want to use wait-handles to accomplish this, take a look at the ManualResetEvent class.
Notifies one or more waiting threads
that an event has occurred.
Call the WaitOne method on it to wait on the event, and the Set method to signal it.
Example (horribly contrived code):
var afterT1Event = new ManualResetEvent(false);
var afterT2Event = new ManualResetEvent(false);
Thread t1 = new Thread(() => { Task1(); afterT1Event.Set(); });
Thread t2 = new Thread(() => { afterT1Event.WaitOne(); Task2(); afterT2Event.Set(); });
Thread t3 = new Thread(() => { afterT2Event.WaitOne(); Task3(); });
t1.Start();
t2.Start();
t3.Start();
If you want to use WaitHandles to acheive these then you could do the following:
declare the following two fields:
static ManualResetEvent handle1 = new ManualResetEvent(false);
static ManualResetEvent handle2 = new ManualResetEvent(false);
then at the end of Task1, add this:
handle1.Set();
at the beginning of Task2, add:
handle1.WaitOne();
then at the end, add
handle2.Set();
then finally at the beginning of Task3 add
handle2.WaitOne();
This feels very artificial, almost like homework...
... but basically you can use Join on a thread to wait for it.
Or the old msdn tutorial/example is very reasonable on this: http://msdn.microsoft.com/en-us/library/aa645740(VS.71).aspx
You could use ManualResetEvents and WaitHandle.WaitAny. Basically when one thread is done you would notify the other thread by using a ManualResetEvent (ManualResetEvent.Set()).
ManualResetEvent threadFinished = new ManualResetEvent(false);
//You would set this in the thread that has finished
threadFinished.Set()
//You would use this in the thread that you want to wait for this event to be signalled
int nWait = WaitHandle.WaitAny(new ManualResetEvent[] { threadFinished }, 10, true);
//if yes stop thread
if (nWait == 0)
{
//Thread is finished
}
i think using thread.join() will be more simpler any other solution
I have a WPF application that kicks off 3 threads and needs to wait for them to finish. I have read many posts here that deal with this but none seem to address the situation where the thread code calls Dispatcher.Invoke or Dispatcher.BeginInvoke. If I use the thread's Join() method or a ManualResetEvent, the thread blocks on the Invoke call. Here's a simplified code snippet of an ugly solution that seems to work:
class PointCloud
{
private Point3DCollection points = new Point3DCollection(1000);
private volatile bool[] tDone = { false, false, false };
private static readonly object _locker = new object();
public ModelVisual3D BuildPointCloud()
{
...
Thread t1 = new Thread(() => AddPoints(0, 0, 192));
Thread t2 = new Thread(() => AddPoints(1, 193, 384));
Thread t3 = new Thread(() => AddPoints(2, 385, 576));
t1.Start();
t2.Start();
t3.Start();
while (!tDone[0] || !tDone[1] || !tDone[2])
{
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background, new ThreadStart(delegate { }));
Thread.Sleep(1);
}
...
}
private void AddPoints(int scanNum, int x, int y)
{
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
z = FindZ(x, y);
if (z == GOOD_VALUE)
{
Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal,
(ThreadStart)delegate()
{
Point3D newPoint = new Point3D(x, y, z);
lock (_locker)
{
points.Add(newPoint);
}
}
);
}
}
}
tDone[scanNum] = true;
}
}
from the main WPF thread...
PointCloud pc = new PointCloud();
ModelVisual3D = pc.BuildPointCloud();
...
Any ideas about how to improve this code would be much appreciated. It seems like this should be a very common problem, but I can't seem to find it properly addressed anywhere.
Assuming you can use .NET 4, I'm going to show you how to do this in a much cleaner way that avoids sharing mutable state across threads (and thus, avoids locking).
class PointCloud
{
public Point3DCollection Points { get; private set; }
public event EventHandler AllThreadsCompleted;
public PointCloud()
{
this.Points = new Point3DCollection(1000);
var task1 = Task.Factory.StartNew(() => AddPoints(0, 0, 192));
var task2 = Task.Factory.StartNew(() => AddPoints(1, 193, 384));
var task3 = Task.Factory.StartNew(() => AddPoints(2, 385, 576));
Task.Factory.ContinueWhenAll(
new[] { task1, task2, task3 },
OnAllTasksCompleted, // Call this method when all tasks finish.
CancellationToken.None,
TaskContinuationOptions.None,
TaskScheduler.FromCurrentSynchronizationContext()); // Finish on UI thread.
}
private void OnAllTasksCompleted(Task<List<Point3D>>[] completedTasks)
{
// Now that we've got our points, add them to our collection.
foreach (var task in completedTasks)
{
task.Result.ForEach(point => this.points.Add(point));
}
// Raise the AllThreadsCompleted event.
if (AllThreadsCompleted != null)
{
AllThreadsCompleted(this, EventArgs.Empty);
}
}
private List<Point3D> AddPoints(int scanNum, int x, int y)
{
const int goodValue = 42;
var result = new List<Point3D>(500);
var points = from pointX in Enumerable.Range(0, x)
from pointY in Enumerable.Range(0, y)
let pointZ = FindZ(pointX, pointY)
where pointZ == goodValue
select new Point3D(pointX, pointX, pointZ);
result.AddRange(points);
return result;
}
}
Consumption of this class is easy:
// On main WPF UI thread:
var cloud = new PointCloud();
cloud.AllThreadsCompleted += (sender, e) => MessageBox.Show("all threads done! There are " + cloud.Points.Count.ToString() + " points!");
Explanation of this technique
Think about threading differently: instead of trying to synchronize thread access to shared data (e.g. your point list), instead do heavy lifting on the background thread but don't mutate any shared state (e.g. don't add anything to the points list). For us, this means looping over X and Y and finding Z, but not adding them to the points list in the background thread. Once we've created the data, let the UI thread know we're done and let him take care of adding the points to the list.
This technique has the advantage of not sharing any mutable state -- only 1 thread accesses the points collection. It also has the advantage of not requiring any locks or explicit synchronization.
It has another important characteristic: your UI thread won't block. This is generally a good thing, you don't want your app to appear frozen. If blocking the UI thread is a requirement, we'd have to rework this solution a bit.