I have the below code and certainly I have a deadlock using Threads, but why not happens with tasks?
private static object lockObject1 = new object();
private static object lockObject2 = new object();
static void Main(string[] args)
{
Console.Title = "Deadlocks";
//Using tasks.
Task ourTask1 = new Task(SingleMethod_A);
ourTask1.Start();
Task ourTask2 = new Task(SingleMethod_B);
ourTask2.Start();
//Using threads.
//Thread ourThread1 = new Thread(new ThreadStart(SingleMethod_A));
//Thread ourThread2 = new Thread(new ThreadStart(SingleMethod_B));
//ourThread1.Start();
//ourThread2.Start();
Console.WriteLine("Deadlock");
}
public static void SingleMethod_A()
{
lock (lockObject1)
{
Thread.Sleep(1000);
lock (lockObject2)
{
Console.WriteLine("not possible.");
}
}
}
public static void SingleMethod_B()
{
lock (lockObject2)
{
Thread.Sleep(1000);
lock (lockObject1)
{
Console.WriteLine("not possible.");
}
}
}
Tasks can certainly dead lock. It is also important to keep in mind that Tasks aren't threads - they may run on one from the thread pool.
Why you aren't seeing it is because your case is a trivial example and .Start doesn't have to use separate threads. Try changing your calls to start to Task.Run(action) instead to see the deadlock:
Task.Run(() => SingleMethod_A());
Task.Run(() => SingleMethod_B());
Related
According to article class below is not thread safe:
I have code which gets into lock while according to my understanding has different synchronization content:
[Synchronization]
public class Deadlock : ContextBoundObject
{
public DeadLock Other;
public void Demo() { Thread.Sleep (1000); Other.Hello(); }
void Hello() { Console.WriteLine ("hello"); }
}
public class Test
{
static void Main()
{
Deadlock dead1 = new Deadlock();
Deadlock dead2 = new Deadlock();
dead1.Other = dead2;
dead2.Other = dead1;
new Thread (dead1.Demo).Start();
dead2.Demo();
}
}
It does and it is fine. But I decided to play with synchronization attributes by setting:
[Synchronization(SynchronizationAttribute.SUPPORTED)]
SUPPORTED means :
Joins the existing synchronization context if instantiated from
another synchronized object, otherwise remains unsynchronized
Since console application has no synchronization content I expect both object will have no synchronization object and should not get into deadlock. But I still have deadlock. Why?
Further have removed [Synchronization] attribute at all. Still have deadlock. What influence makes [Synchronization] attribute to object?
Here you are creating circular dependency between thread , that might lead you to stackoverflow exception , as you are not catching excpetion here you are might not able to view it. I suggest you make use of UnObservedExcpetion handler that will give you excpetion or try to handle excpetion in that same function by putting try, catch block.
To avoid this kind of situation you better make use of AutoResetEvent. below is sample code for the same.
public class MyThreadTest
{
static readonly AutoResetEvent thread1Step = new AutoResetEvent(false);
static readonly AutoResetEvent thread2Step = new AutoResetEvent(true);
void DisplayThread1()
{
while (true)
{
thread2Step.WaitOne();
Console.WriteLine("Display Thread 1");
Thread.Sleep(1000);
thread1Step.Set();
}
}
void DisplayThread2()
{
while (true)
{
thread1Step.WaitOne();
Console.WriteLine("Display Thread 2");
Thread.Sleep(1000);
thread2Step.Set();
}
}
void CreateThreads()
{
// construct two threads for our demonstration;
Thread thread1 = new Thread(new ThreadStart(DisplayThread1));
Thread thread2 = new Thread(new ThreadStart(DisplayThread2));
// start them
thread1.Start();
thread2.Start();
}
public static void Main()
{
MyThreadTest StartMultiThreads = new MyThreadTest();
StartMultiThreads.CreateThreads();
}
}
Previously, I ran a method in a thread like this:
static void procedure() { while (x) thread.sleep() }
static Thread runner;
...
void method(){
runner = new Thread(new ThreadStart(procedure));
runner.Start();
}
I changed this in an attempt to have a single thread that I can start at different points.
static void procedure() { while (x) thread.sleep() }
static Thread runner;
void main(){
runner = new Thread(new ThreadStart(procedure));
...
}
...
void method(){
runner.Start();
}
This no longer runs the thread as expected. The program halts, which I believe is due to the new thread running on the main thread.
Why is it no longer running on a seperate thread?
Works fine, here's an example based on your code.
class Program
{
static void procedure()
{
while (true)
{
Thread.Sleep(1000);
Console.WriteLine("Sleep");
}
}
static Thread runner;
static void Main(string[] args)
{
runner = new Thread(new ThreadStart(procedure));
Console.WriteLine("Here!");
runner.Start();
Console.WriteLine("And now here...");
}
}
I'm trying to implement AutoResetEvent. For the purpose I use a very simple class :
public class MyThreadTest
{
static readonly AutoResetEvent thread1Step = new AutoResetEvent(false);
static readonly AutoResetEvent thread2Step = new AutoResetEvent(false);
void DisplayThread1()
{
while (true)
{
Console.WriteLine("Display Thread 1");
Thread.Sleep(1000);
thread1Step.Set();
thread2Step.WaitOne();
}
}
void DisplayThread2()
{
while (true)
{
Console.WriteLine("Display Thread 2");
Thread.Sleep(1000);
thread2Step.Set();
thread1Step.WaitOne();
}
}
void CreateThreads()
{
// construct two threads for our demonstration;
Thread thread1 = new Thread(new ThreadStart(DisplayThread1));
Thread thread2 = new Thread(new ThreadStart(DisplayThread2));
// start them
thread1.Start();
thread2.Start();
}
public static void Main()
{
MyThreadTest StartMultiThreads = new MyThreadTest();
StartMultiThreads.CreateThreads();
}
}
But this is not working. Th usage seem very straight-forward so I would appreciate if someone is able to show me what's wrong and where is the problem with the logic which i implement here.
The question is not very clear but I'm guessing you're expecting it to display 1,2,1,2...
Then try this:
public class MyThreadTest
{
static readonly AutoResetEvent thread1Step = new AutoResetEvent(false);
static readonly AutoResetEvent thread2Step = new AutoResetEvent(true);
void DisplayThread1()
{
while (true)
{
thread2Step.WaitOne();
Console.WriteLine("Display Thread 1");
Thread.Sleep(1000);
thread1Step.Set();
}
}
void DisplayThread2()
{
while (true)
{
thread1Step.WaitOne();
Console.WriteLine("Display Thread 2");
Thread.Sleep(1000);
thread2Step.Set();
}
}
void CreateThreads()
{
// construct two threads for our demonstration;
Thread thread1 = new Thread(new ThreadStart(DisplayThread1));
Thread thread2 = new Thread(new ThreadStart(DisplayThread2));
// start them
thread1.Start();
thread2.Start();
}
public static void Main()
{
MyThreadTest StartMultiThreads = new MyThreadTest();
StartMultiThreads.CreateThreads();
}
}
I was trying to create an example for deadlock. I tried the following code. But instead of creating deadlock, it worked like charm. Help me in understanding why it didn't create a deadlock. What change in this code would create a deadlock?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ReferenceTypes
{
class DeadLockExample
{
static int a;
static int b;
public static void Main(string[] args)
{
DeadLockExample.a = 20;
DeadLockExample.b = 30;
DeadLockExample d = new DeadLockExample();
Thread tA = new Thread(new ThreadStart(d.MethodA));
Thread tB = new Thread(new ThreadStart(d.MethodB));
tA.Start();
tB.Start();
Console.ReadLine();
}
private void MethodA()
{
lock (this)
{
Console.WriteLine(a);
Thread.Sleep(1000);
Console.WriteLine(b);
}
}
private void MethodB()
{
lock (this)
{
Console.WriteLine(b);
Thread.Sleep(1000);
Console.WriteLine(a);
}
}
}
}
As everyone else has said, two locks acquired in different orders, so that each is waiting on the other. I also changed one of the Sleep lengths to ensure a high probability of the deadlock occurring.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ReferenceTypes
{
class DeadLockExample
{
static int a;
static int b;
static object lockedObjA = new object();
static object lockedObjB = new object();
public static void Main(string[] args)
{
DeadLockExample.a = 20;
DeadLockExample.b = 30;
DeadLockExample d = new DeadLockExample();
Thread tA = new Thread(new ThreadStart(d.MethodA));
Thread tB = new Thread(new ThreadStart(d.MethodB));
tA.Start();
tB.Start();
Console.ReadLine();
}
private void MethodA()
{
lock (DeadLockExample.lockedObjA)
{
Console.WriteLine(a);
Thread.Sleep(1200);
lock (DeadLockExample.lockedObjB) {
Console.WriteLine(b);
}
}
}
private void MethodB()
{
lock (DeadLockExample.lockedObjB)
{
Console.WriteLine(b);
Thread.Sleep(1000);
lock (DeadLockExample.lockedObjA) {
Console.WriteLine(a);
}
}
}
}
}
2 locks, 2 threads.
Thread A takes lock A, sleeps and then tries to take lock B. Thread B takes lock B, sleeps and then tries to take lock A, equals a Deadlock.
[Thread A has to sleep long enough so that thread B takes lock B before thread A attempts to acquire it]
Here are 3 different ways you can cause a deadlock. This list is not exhaustive.
Call a blocking method from within a lock section.
In this example thread A acquires a lock and then immediately calls a blocking method while at the same time thread B attempts to acquire the same lock, but gets hung because thread A is waiting for thread B to signal the event before it will release the lock.
public class Example
{
ManualResetEvent m_Event = new ManualResetEvent(false);
void ThreadA()
{
lock (this)
{
m_Event.WaitOne();
}
}
void ThreadB()
{
lock (this)
{
m_Event.Set();
}
}
}
Acquire two locks out of order.
No explanation is needed here since this is a well known problem.
public class Example
{
private object m_LockObjectA = new object();
private object m_LockObjectB = new Object();
void ThreadA()
{
lock (m_LockObjectA) lock (m_LockObjectB) { }
}
void ThreadB()
{
lock (m_LockObjectB) lock (m_LockObjectA) { }
}
}
The lock-free deadlock.
This is one my favorite illustrations of a deadlock because no lock or blocking method is involved. The subtlety of the problem is enough to confound even those who are familiar with threading. The issue here is related to the absence of memory barriers. Thread A waits for thread B to set the signal flag while at the same time thread B waits for thread A to reset it all the while neither thread is seeing the changes the other is making because the compiler, JIT, and hardware are free to optimize the reads and writes of the flag in manner that is non-intuitive.
public class Example
{
private bool m_Signal = false;
void ThreadA()
{
while (!m_Signal);
m_Signal = false;
}
void ThreadB()
{
m_Signal = true;
while (m_Signal);
}
}
From Wikipedia -
A deadlock is a situation wherein two
or more competing actions are each
waiting for the other to finish, and
thus neither ever does.
You don't fulfil this requirement with your code above - there's never a point where both thread A and thread B are waiting on each other to complete.
I am making an application in C# which uses a winform as the GUI and a separate thread which is running in the background automatically changing things. Ex:
public void Run()
{
while(true)
{
printMessageOnGui("Hey");
Thread.Sleep(2000);
// Do more work
}
}
How would I make it pause anywhere in the loop, because one iteration of the loop takes around 30 seconds. So I wouldn't want to pause it after its done one loop, I want to pause it on time.
var mrse = new ManualResetEvent(false);
public void Run()
{
while (true)
{
mrse.WaitOne();
printMessageOnGui("Hey");
Thread.Sleep(2000); . .
}
}
public void Resume() => mrse.Set();
public void Pause() => mrse.Reset();
You should do this via a ManualResetEvent.
ManualResetEvent mre = new ManualResetEvent();
mre.WaitOne(); // This will wait
On another thread, obviously you'll need a reference to the mre
mre.Set(); // Tells the other thread to go again
A full example which will print some text, wait for another thread to do something and then resume:
class Program
{
private static ManualResetEvent mre = new ManualResetEvent(false);
static void Main(string[] args)
{
Thread t = new Thread(new ThreadStart(SleepAndSet));
t.Start();
Console.WriteLine("Waiting");
mre.WaitOne();
Console.WriteLine("Resuming");
}
public static void SleepAndSet()
{
Thread.Sleep(2000);
mre.Set();
}
}
You can pause a thread by calling thread.Suspend but that is deprecated. I would take a look at autoresetevent for performing your synchronization.