简体   繁体   中英

Static Variables and Multi Threading

Is it a good practice to have a static variable as counter that can be updated by all the threads in a C#.NET program?
Sample Code:

public class SomeTask 
{
static int count = 0;
public void Process()
{

    while(true)
    {
        //some repeated task
        count++;
        if(count>100000)
        {
            count=0;
            break;
        }
    }
}
}

public class WorkerRole : RoleEntryPoint
{
   public override void Run()
    {
    while(true)
    {

        for (int i = 0; i < maxTasks; i++)
        {
            this.Tasks[i] = Task.Factory.StartNew(() => (new SomeTask()).Process());
        }
        Task.WaitAll(this.Tasks);

        //every 100000 in counter needs some updates at program level
    }
}
}

Yes that is a good approach but make sure you use an atomic type . I would have performance concerns if the counter increment operations were implemented using thread safe code as opposed to atomic operations.

To implement a counter, you'll be making use of ++ and -- . These, in general, are not thread safe for the primitive types in C#.

See Is the ++ operator thread safe?

Atomic types in C#?

See reference What operations are atomic in C#?

This answer suggests that 32 bit integral types are atomic on 32 bit machines, 64 bit integral types are atomic on 64 bit machines.

If you can't avoid it then it's fine. It's best to use Interlocked class increment the counter:

if (Interlocked.Increment(ref counter) % 100000 == 0) {
    // Do something every hundred thousand times
    // Use "== 1" if you also want to do it on the first iteration
}

I'll leave the code below for the case when you only need to know the count at the end

In your case you could keep the count as an instance field (ie non-static), add public getter and sum up all the counters after all tasks have finished:

public class SomeTask 
{
    int count = 0;
    public int Count { get { return count; } }

    public void Process()
    {

        while(true)
        {
            //some repeated task
            count++;

            if (something)
                break;
        }
    }        
}

var someTasks = new List<SomeTask>();
for (int i = 0; i < maxTasks; i++)
{
    var someTask = new SomeTask();
    someTasks.Add(someTask);
    this.Tasks[i] = Task.Factory.StartNew(() => someTask.Process());
}
Task.WaitAll(this.Tasks);

// Your total count
var total = someTasks.Sum(t => t.Counter);

Yes , it is perfectly all right as long as you keep it thread-safe and syncronized in threads. You can use lock for syncronization. You can read more about thread safety and static members here and here . You can also use Interlocked.Increment to increament the counter in a thread-safe way. Read more about thread safety with increament operator here in Eric Lippert answer .

class Account
{
    int count;
    private Object thisLock = new Object();

    public void Add(decimal amount)
    {
        //your code
        lock (thisLock)
        {
           count = count + 1;
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM