using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ThreadExample
{
public class Info
{
public int Counter;
private static object _lock = new object();
private List<Thread> ThreadList;
public Info(int counter)
{
Counter = counter;
ThreadList = new List<Thread>();
ThreadList.Add(new Thread(ThreadBody));
ThreadList.Add(new Thread(ThreadBody));
ThreadList[0].Name = "t1";
ThreadList[1].Name = "t2";
}
public void Start()
{
ThreadList.ForEach(t => t.Start(t.Name));
}
public void ThreadBody(object name)
{
while (Counter != 20)
{
lock (_lock)
{
Counter++;
Console.WriteLine("Thread {0} : the value of the counter is {1}", name.ToString(), Counter);
}
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ThreadExample
{
class Program
{
static void Main(string[] args)
{
Info info = new Info(0);
info.Start();
}
}
}
if the lock is just lock counter ++
lock (_lock)
{
Counter++;
}
I don’t have an infinite loop, but if the lock is like in example, it run infinite loop
It could be that when
Countergets to 19 both threads enter the loop and it ends up getting incremented to 21 before they test the value again.You’ll need to hold the lock while reading the value of
Counter. A double check ofCountermight be adequate (re-read it again inside thewhileloop while holding the lock). However, I’m not sure about this because my head just can’t keep track of all the details of various threading memory models between native, .NET, Java, and whatever. Even on .NET the ECMA model is apparently different than what MS guarantees for their CLR (see http://msdn.microsoft.com/en-us/magazine/cc163715.aspx and http://www.bluebytesoftware.com/blog/PermaLink,guid,543d89ad-8d57-4a51-b7c9-a821e3992bf6.aspx). For more details on why double-checking might or might not work, search for “double checked locking” – there’s an awful lot of complexity behind something that apparently should be simple.For example, here’s snippet of a run on my machine:
You’ll notice that
t2stops once it getsCounterto 20, but thet1doesn’t notice that. It’s already entered the loop (or decided to enter the loop) thinking thatCounteris 1 (or maybe 2 or something else – just not 20).