2

我有一个示例应用程序,想知道是否有人可以对此有所了解。当我在 for 循环上设置断点时,进入调试器中的代码,为什么它会从一个线程切换到另一个线程?它在运行时运行应用程序时这样做......请参见下面的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TPLSample
{
    class Program
    {

        static void Main(string[] args)
        {
           Management m = new Management();

           Task a = new Task(() => m.Operation1());
           a.Start();
           Task b = new Task(() => m.Operation2());
           b.Start();


            Console.ReadLine();
        }
    }
    public class Management
    {
        A a = null;
        B b = null;

        public void Operation1()
        {
            a = new A();

        }
        public void Operation2()
        {
            b = new B();
        }
    }
    public class A
    {  Client a = new Client();
        public A()
        {
            while (true)
            {
                a.Test("Im AAAAA");
            }
        }
    }
    public class B
    {
        Client a = new Client();
        public B()
        {
            while (true)
            {
                a.Test("Im BBBBB");
            }
        }
    }
    public class Client
    {
        Object ibj = new Object();


        public void Test(string item)
        {
            lock (ibj)
            {
                for (int i = 0; i < 200000; i++)
                {
                    Console.WriteLine(item);
                }
            }

        }
    }
}

其结果是 As 和 Bs 的混合。锁不是应该阻塞线程以使结果按顺序结束吗?我正在编写的应用程序中也发生了同样的情况,除了 WHILE 循环永远运行(每个任务都需要连续轮询)。请注意,我正在启动两项任务,因为如果 WHILE 循环要永远运行,我不希望一个 WHILE 循环阻止另一个运行。如何使它们按顺序执行 CLIENT 类中的该功能?

4

2 回答 2

7

This happens because if you trace your object creation tree carefully you will notice that each thread is using a different lock object, thus rendering your lock statement useless.

Your object creation happens like this:

                 new A() -> new Client() -> new Object()
                / 
new Management()
                \
                 new B() -> new Client() -> new Object()

You are using the last two objects on the right as locks, and you can clearly see that they are different objects.

Try to make the lock static:

public class Client
{
    static Object ibj = new Object();
    ...

or otherwise rethink your hierarchy to pass the same lock to both Tasks.

于 2012-05-16T17:36:17.430 回答
2

每个对象都必须能够访问同一个对象才能使锁起作用。您可以通过将 ibj 对象设为静态或将其传递给 Client 类来实现此目的。

public class Client
{
    static Object ibj = new Object();


    public void Test(string item)
    {
        lock (ibj)
        {
            for (int i = 0; i < 200000; i++)
            {
                Console.WriteLine(item);
            }
        }

    }
}
于 2012-05-16T17:38:53.643 回答