Reputation: 13
Scenario, I am having multiple threads trying to sharing a static global variable counter. After which I would add it into a List of integers and this list would be used in another thread to check out some details.
I realized after even using LOCK on the global variable counter, I still get duplicate numbers
Please pardon my explanation, codes would speak more.
Problem would be different threads may be generated a same counter value( which I don't want). I want a running number without duplicates
class Test
{
private Object _thisLock = new Object();
List<int> listing = new List<int>(); //shared LIST
public void Main()
{
//array of threads
for (int i = 0; i < 8; i++)
{
Thread th = new Thread(Work);
th.Name = "Thread" + i;
th.Start();
}
Thread.Sleep(5000);
//Start checking for duplicates
Thread checker = new Thread(Checker);
checker.Start();
}
private void Work()
{
Object _thisLock = new Object();
while (true)
{
int a = Singleton.Instance.Counter++;
Console.WriteLine(Thread.CurrentThread.Name);
Console.WriteLine("WOrk : " + a);
lock (_thisLock)
{
listing.Add(a);
}
Thread.Sleep(1000);
}
}
private void Checker()
{
Object _thisLock = new Object();
while (true)
{
lock (_thisLock)
{
List<int> selflist = new List<int>();
selflist.AddRange(listing); ;
foreach (int p in selflist)
{
if (selflist.FindAll(item => item.Equals(p)).Count() > 1)
{
Console.WriteLine("Check!!!!!!!!!!!!!!!!!! : " + p);
}
}
}
Thread.Sleep(5000);
}
}
}
static void Main()
{
Test t = new Test();
t.Main();
}
public sealed class Singleton
{
private static volatile Singleton instance;
private static object syncRoot = new Object();
private readonly Object _thisLock = new Object();
private Singleton() { }
public static Singleton Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}
private volatile static int _counter;
public int Counter
{
get
{
lock (_thisLock)
{
return _counter;
}
}
set
{
lock (_thisLock)
{
_counter = value;
}
}
}
}
Upvotes: 1
Views: 180
Reputation: 5083
In your Work
method every thread have it's own lock object _thisLock
.
Remove this statement in your work method and let it use private lockobject of the class:
Object _thisLock = new Object();
Upvotes: 4
Reputation: 156968
Why not just move the counter into the lock
and make the lock shared by moving it to the class level?
private object _thisLock = new object();
...
lock (_thisLock)
{
int a = Singleton.Instance.Counter++;
listing.Add(a);
}
Also, use a thread safe collection type, like ConcurrentBag
.
Upvotes: 2