简体   繁体   中英

Does Task Parallel Library (TPL) handle race condition

I am trying to understand the benefits of Task Parallel library over using traditional multi threading and when I think about the below situation, I am stuck thinking does it handle race condition or do we need to handle this in our code?

Here is my code:

 int depdt = 0;    
 Parallel.For(1, 10, mem =>
        {

            for (int dep = 1; dep <= 10; dep++)
            {
                depdt = dep;
                Console.WriteLine("MEMBER: " + mem + " " + "Dependent: " + dep);
            }

            Console.WriteLine("Dep Value: " + depdt + " " + "mem: " + mem);
        });
        Console.ReadKey();

I ran it couple of times and I don't see any thread interfering/overwriting the the "depdt" variable. But I need to confirm this. (or) To make it thread safe should I manually create an instance of class and implement it like the below code to avoid race conditions

 int depdt = 0;
        Parallel.For(1, 10, mem =>
        {
              Worker worker = new Worker();
              worker.DoWork(mem);

        });
        Console.ReadKey();

  public class Worker
{
    public void DoWork(int mem)
    {

        int depdt = 0;
        for (int dep = 1; dep <= 10; dep++)
        {
            depdt = dep;
            Console.WriteLine("MEMBER: " + mem + " " + "Dependent: " + dep);
        }

        Console.WriteLine("Dep Value: " + depdt  +" "+ "mem: "+ mem);
    }
}

Response to @yms: I mean when using normal threads the varaible depdt becomes unreliable. Here is my code:

for (int mem = 1; mem <= 10; mem++)
        {
            var t= new Thread(state =>
            {
                for (int dep = 1; dep <= 10; dep++)
                {
                    depdt = dep;
                    Console.WriteLine("MEMBER: " + mem + " " + "Dependent: " + dep);
                }

                Console.WriteLine("Dep Value: " + depdt + " " + "mem: " + mem);
            });

            t.Start(string.Format("Thread{0}", mem));
        }
        Console.ReadKey();

Here is my output screen: Infact both mem and dep variables have become unreliable

在此处输入图片说明

If you expect your program to always write Dep Value: 10 , then yes, your program is subject to a race condition that may lead to other values being printed. To demonstrate the issue, just introduce a delay within the inner loop:

int depdt = 0;
Parallel.For(1, 10, mem =>
{
    for (int dep = 1; dep <= 10; dep++)
    {
        depdt = dep;
        Console.WriteLine("MEMBER: " + mem + " " + "Dependent: " + dep);
        Thread.Sleep(mem * 100);   // delay introduced here
    }
    Console.WriteLine("Dep Value: " + depdt + " " + "mem: " + mem);
});
Console.ReadKey();

The reason that your program appears to behave correctly is that the inner loop takes very little time to execute, probably completing within a single time quantum allocated to the thread.

To avoid the race condition, you just need to move the depdt declaration inside the anonymous function passed to Parallel.For . This would cause each thread to have its own variable, avoiding conflicts.

Parallel.For(1, 10, mem =>
{
    int depdt = 0;
    for (int dep = 1; dep <= 10; dep++)
    {
        depdt = dep;
        Console.WriteLine("MEMBER: " + mem + " " + "Dependent: " + dep);
    }
    Console.WriteLine("Dep Value: " + depdt + " " + "mem: " + mem);
});

No. Task parallel library does not handles the race conditions by default. You need to take care of synchronizing the access to the shared resources.

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