the use of the lock keyword over different threads - c#

I am thinking that when I start my first thread, it should print "one + n" and lock l,then after this, it should start the second thread and print "two + n".
What actually happens, is that when I run the program I get random results, sometimes printing "one + n", other times printing "two + n"
My understanding of this is obviously flawed - why?
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class locked
{
public long numtochange { get; set; }
public string threadname { get; set; }
}
class Program
{
public static locked l;
static void Main(string[] args)
{
l = new locked();
(new Thread(x => { l.threadname = "one"; Print(l); })).Start();
(new Thread(x => { l.threadname = "two"; Print(l); })).Start();
Console.ReadLine();
}
public static void Print(locked l)
{
lock (l)
{
for (long i = 0; i < 1000; i++)
{
l.numtochange = i;
Console.WriteLine(l.threadname + " " + l.numtochange);
}
}
}
}
}

This part of your code:
l.threadname = "one";
and the corresponding one with = "two" are not locked. Hence they can interleave randomly - sometimes the string "one" ends up in l.threadname and sometimes it is being overwritten by "two". Then, the first thread that manages to get to the lock statement in the Print function does its job and the other one waits.
The simplest fix, if you want them to run sequentially, is to wrap both statements with the lock keyword, like this:
lock (l) { l.threadname = "one"; Print(l); }
(lock is reentrant so there will be no problem with another lock in Print).
However if they always run one after another then there is no point in using threads.

Related

Program that writes numbers until I write a string to stop it

I am required to write a program that prints out numbers until I write in the console window a simple string "stop". The numbers are supposed to go on infinitely until the condition is met.
I tried:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp3
{
internal class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 1000000000;)
{
Console.WriteLine(i);
string a = Console.ReadLine();
if (a == "stop")
{
break;
}
i++;
}
}
}
}
But, there is a delay waiting for my input every time, it's not constant.
You are asking for a non blocking console read. THats not simple.
One way is to peek to see if a key is available to read
int number = 0;
while (true)
{
Console.WriteLine(number);
number++;
if (Console.KeyAvailable)
{
var s = Console.ReadLine();
if (s == "stop")
break;
}
}

Concurrent increment g = g + 1 of a static variable appears atomic, but shouldn't be?

Can't find why code below with commented Monitor works like synchronized while writing to to g and always returns g=50. I was expecting some discrepancy an result less than 50.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace _7_monitor
{
class Program
{
static object sync = new object();
static int g = 0;
static Barrier b = new Barrier(6, (b) => { Console.WriteLine("barier reached"); } );
public static void tjob(object obj)
{
int t = (int)obj;
for (int i = 0; i < 10; i++)
{
//Monitor.Enter(sync);
g = g + 1;
//Monitor.Exit(sync);
Console.WriteLine("thr {0} iter={1}", t , i);
}
b.SignalAndWait();
}
static void Main(string[] args)
{
for (int i = 0; i < 5; i++)
{
Thread d = new Thread(tjob);
d.Start(i);
}
Console.WriteLine("waiting");
b.SignalAndWait();
Console.WriteLine("g={0}",g);
Console.ReadLine();
}
}
}
As others have pointed out, a loop of 10 will complete so quickly that there's a good chance that the other threads haven't even started yet, so you've likely got sequential access to the global static variable g, in any event, hence the apparantly observed consistent result.
With a longer loop (I've taken some of the fluff out) with no protection around g, we do get something resembling a random number generator.
var threads = new List<Thread>();
for (var i = 0; i < 5; i++)
{
var d = new Thread(x => {
for (var loop = 0; loop < 100000; loop++)
{
// unsynchronized mutation
g = g + 1;
}
});
d.Start(i);
threads.Add(d);
}
foreach (var t in threads)
{
t.Join();
}
Console.WriteLine("g={0}", g); // 158609, 173331, 127983, ... (i7 with 4 HT Cores)
As per #Jurgis' comment, instead of a Monitor or lock, Interlocked.Increment has been provided to .Net
Replacing g = g + 1 with Interlocked.Increment(ref g); returns the expected:
g=500000
(and obviously, in the real world, there would be absolutely no point in parallelizing work which would just contend for a shared variable)

How many threads in the application? How to set the count of semaphore?

The semaphore means to specify the count how many threads can enter into critical region at a time.
The following code set the count is 5.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static Semaphore semaphore = new Semaphore(5, 5);
static void Main(string[] args)
{
Task.Factory.StartNew(() =>
{
for (int i = 1; i <= 15; ++i)
{
PrintSomething(i);
if (i % 5 == 0)
{
Thread.Sleep(2000);
}
}
});
Console.ReadLine();
}
public static void PrintSomething(int number)
{
semaphore.WaitOne();
Console.WriteLine(number);
semaphore.Release();
}
}
}
Which means each time we can have 5 threads running at any time. The printing result verifies the point.
My question is that I don't see so many threads running. Say 15 threads running, each time only can let 5 threads to be coexisting. There are only two threads.
Am I misunderstood something?
You start one additional thread using Task.Factory.StartNew() and that's it. In that thread you are calling the PrintSomething() method sequentially, so your thread output screenshot is correct.
Change your code as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace SempahoreTest1
{
class Program
{
static Semaphore semaphore = new Semaphore(5, 5);
static void Main(string[] args)
{
for (int i = 1; i <= 15; ++i)
{
Task.Factory.StartNew((state) =>
{
int number = (int)state;
PrintSomething(number);
if (i % 5 == 0)
{
Thread.Sleep(2000);
}
}, i);
}
Console.ReadLine();
}
public static void PrintSomething(int number)
{
semaphore.WaitOne();
try
{
Console.WriteLine("Thread: {0}, Number: {1}", Thread.CurrentThread.ManagedThreadId, number);
}
finally
{
semaphore.Release();
}
}
}
}
Update:
A better explanation, how a semaphore works, would be:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace SempahoreTest1
{
class Program
{
static Semaphore semaphore = new Semaphore(5, 5);
static Random random = new Random();
static void Main(string[] args)
{
Parallel.For(1, 16, PrintSomething);
Console.ReadLine();
}
public static void PrintSomething(int number)
{
semaphore.WaitOne();
try
{
Console.WriteLine("Thread: {0}, Number: {1}, Access granted", Thread.CurrentThread.ManagedThreadId, number);
// sleep to simulate long running method
Thread.Sleep(random.Next(1000, 5000));
}
finally
{
semaphore.Release();
Console.WriteLine("Thread: {0}, Number: {1}, Semaphore released", Thread.CurrentThread.ManagedThreadId, number);
}
}
}
}
The parallel loop calls PrintSomething() from different threads. On every call the semaphore counter is decreased, until it reaches 0. The next call of PrintSomething() blocks on semaphore.WaitOne(), until the first calls semaphore.Release(), that increments the semaphore counter again. And so on...
The first 5 calls are very fast, because the maximum semaphore count (5) is available. Then, due to the different sleep times, the method call outputs show you, how the semaphore works.

Bug when debugging code without breakpoints

Im getting a bug where i call for two ints to get randomly generated by the same method but they always return the same number when releasing the code in debug mode
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Kortspil
{
public class Kort
{
public int FåKortNummer()//Get card number
{
System.Random KortNummer = new System.Random();
int kort = KortNummer.Next(1, 14);
ErKortTrukket(kort);//is drawn
return kort;
}
}
class Program
{
static void Main(string[] args)
{
Kort SpillerEt = new Kort();
Kort SpillerTo = new Kort();
int SpillerEtKort = SpillerEt.FåKortNummer();//random number 1
Console.WriteLine("Spiller et har trukket: " + SpillerEtKort.ToString());
int SpillerToKort = SpillerTo.FåKortNummer(); // random number 2
Console.WriteLine("Spiller to har trukket: " + SpillerToKort.ToString());
if (SpillerEtKort <= SpillerToKort)
{
Console.WriteLine("Spiller Et vandt denne runde");//player 1 won this round
}
else
{
Console.WriteLine("Spiller to vandt denne runde");//player 2 won this round
}
Console.WriteLine("Tryk Enter for at lukke...");
Console.ReadLine();
}
}
}
You're problem is that you are creating two different Random instances. By default, if you do not supply a seed number, the current time will be used as a seed. However, you're code is executing so quickly, that the same time is being used as a seed (because you're code is executing faster than the smallest resolution of the clock), so the number you receive is the same each time.
The best fix is to create only a single instance of Random. For example, you could change your code to:
public class Kort
{
public static System.Random KortNummer = new System.Random();
public int FåKortNummer()//Get card number
{
int kort = KortNummer.Next(1, 14);
ErKortTrukket(kort);//is drawn
return kort;
}
}

Why does the callback/endinvoke happen after all begin invokes called?

What I'm trying to do is queue up a big list of similar tasks. The time it takes each task to complete is small but there are a lot of them. For each item in the list, I create a delegate and call the delegate.BeginInvoke method then I move to creating the next one.
I would expect in the below example that I would get at least one "****** End Invoke ****" to occur BEFORE all of the begin invokes are called. Instead, it looks like the compiler is starting all of my begin invokes before any end invokes are received.
Is this normal behavior? Is there another way I can send off a task/method on another thread and receive it back while continuing to spur up more tasks?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace AsyncResultTesting
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Starting");
for (int i = 0; i < 100; i++)
{
delMeth d = new delMeth(sleepMethod);
Console.WriteLine(string.Format("Calling the begin invoke from thread: {0} for ID: {1}", Thread.CurrentThread.ManagedThreadId.ToString(), i.ToString()));
IAsyncResult ar = d.BeginInvoke(i, callbackMessage, d);
}
Console.ReadLine();
}
private delegate int delMeth(int id);
private static int sleepMethod(int id)
{
Console.WriteLine(Environment.NewLine + String.Format("Thread: {0} is sleeping. Delegate id is {1}", Thread.CurrentThread.ManagedThreadId.ToString(),id.ToString()));
Console.WriteLine(String.Format("Thread Properties IsThreadPoolThread? = {0} isThreadBackground? = {1} ThreadState: = {2}", Thread.CurrentThread.IsThreadPoolThread.ToString(), Thread.CurrentThread.IsBackground.ToString(), Thread.CurrentThread.ThreadState.ToString()));
Console.WriteLine("");
Thread.Sleep(100);
return id;
}
private static void callbackMessage(IAsyncResult ar)
{
delMeth d = (delMeth)ar.AsyncState;
int result = d.EndInvoke(ar);
Console.WriteLine(Environment.NewLine + "************************ END INVOKE *****************************");
Console.WriteLine(String.Format("Delegate was just called back for id: {0}", result.ToString()));
}
}
}
Unfortunately I have to design this using .NET 3.5 so Task Asynchronous Processing is not available to me.
USR is correct. Everything is functioning how I would expect it to. If i sleep for 10 ms then I see EndInvokes come back in the middle of BeginInvokes.
Thanks USR.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace AsyncResultTesting
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Starting");
for (int i = 0; i < 150; i++) {
delMeth d = new delMeth(sleepMethod);
Console.WriteLine(string.Format("Calling the begin invoke from thread: {0} for ID: {1}", Thread.CurrentThread.ManagedThreadId.ToString(), i.ToString()));
IAsyncResult ar = d.BeginInvoke(i, new AsyncCallback(callbackMessage), d);
}
Console.ReadLine();
}
private delegate int delMeth(int id);
private static int sleepMethod(int id)
{
Console.WriteLine(Environment.NewLine + String.Format("Thread: {0} is sleeping. Delegate id is {1}", Thread.CurrentThread.ManagedThreadId.ToString(),id.ToString()));
Console.WriteLine(String.Format("Thread Properties IsThreadPoolThread? = {0} isThreadBackground? = {1} ThreadState: = {2}", Thread.CurrentThread.IsThreadPoolThread.ToString(), Thread.CurrentThread.IsBackground.ToString(), Thread.CurrentThread.ThreadState.ToString()));
Console.WriteLine("");
Thread.Sleep(10);
return id;
}
private static void callbackMessage(IAsyncResult ar)
{
delMeth d = (delMeth)ar.AsyncState;
int result = d.EndInvoke(ar);
Console.WriteLine(Environment.NewLine + "************************ END INVOKE *****************************");
Console.WriteLine(String.Format("Delegate was just called back for id: {0}", result.ToString()));
}
}
}

Categories