锁无法在C#中工作

时间:2013-08-09 10:29:48

标签: c# asp.net locking

Lock没有按预期工作,这是代码。 我在这里应用线程,但我将它应用于 ASP.NET 应用程序。

class Program
    {
        static void Main(string[] args)
        {
            ThreadManager.CurrentSession = 0;
            for (int i = 0; i < 10; i++)
            {
                CreateWork objCreateWork = new CreateWork();
                ThreadStart start = new ThreadStart(objCreateWork.ProcessQuickPLan);
                new Thread(start).Start();
            }
            Console.ReadLine();
        }
    }

    class CreateWork
    {
        private object CurrentSession = -1;
        public void ProcessQuickPLan()
        {
            lock (CurrentSession)
            {
                CurrentSession = ThreadManager.CurrentSession;
                Console.WriteLine(CurrentSession);
                ThreadManager.CurrentSession = Convert.ToInt32(ThreadManager.CurrentSession) + 1;
            }
        }
    }

    class ThreadManager
    {
        public static object CurrentSession
        {
            get;
            set;
        }
    }

它给了我以下输出

0
0
0
3
4
4
6
7
8
9

我期待

0
1
2
3
4
5
6
7
8
9

我在哪里做错了?

我应该使用此处所述的readonly object C# lock(mylocker) not work

5 个答案:

答案 0 :(得分:3)

问题出在您用来锁定的对象上。您正在使用实例变量,因此每个实例都有自己的lock,这根本就是错误的。

第二个问题是使用-1初始化,这至少令人困惑。

简单的解决方案是static object CurrentSession = new object();

下一期是CurrentSession = ThreadManager.CurrentSession;。这没有任何意义,本质上是错误的。我很惊讶它甚至编译。

class CreateWork
{
    private object CurrentSession = -1;   // boxed int, Id only
    private static object _locker = new object();

    public void ProcessQuickPLan()
    {
        lock (_locker)
        {
            CurrentSession = ThreadManager.CurrentSession;
            Console.WriteLine(CurrentSession);
            ThreadManager.CurrentSession = Convert.ToInt32(ThreadManager.CurrentSession) + 1;
        }
    }
}

总结:目前尚不清楚你在这里要做什么。 CurrentSession似乎有锁定防守和Id的双重角色。不是一个好的计划。

基本上,您需要1个私有静态对象来保护资源。初始化后切勿分配给它。

答案 1 :(得分:2)

问题是你的每个线程都有自己的锁。使CurrentSession静态应该解决问题:只有一个对象可以锁定。您还应该停止在代码中重新分配它。

class CreateWork
{
    private static readonly object LockObject = -1; // Although -1 works here, it's really misleading
    // You should consider replacing the above with a "plain" new object();
    private object CurrentSession = -1; 
    public void ProcessQuickPLan()
    {
        lock (LockObject)
        {
            CurrentSession = ThreadManager.CurrentSession;
            Console.WriteLine(CurrentSession);
            ThreadManager.CurrentSession = Convert.ToInt32(ThreadManager.CurrentSession) + 1;
        }
    }
}

这是working demo on ideone

答案 2 :(得分:0)

我认为问题在于,您将对象锁定在自己的线程中,因此它永远不会被锁定。

更好地使用全局对象,它将被锁定。

答案 3 :(得分:0)

每个线程都包含自己的CreateWork实例和一个锁定器。 试试这段代码:

class Program
{
    static void Main(string[] args)
    {
        ThreadManager.CurrentSession = 0;
        CreateWork objCreateWork = new CreateWork();
        for (int i = 0; i < 10; i++)
        {
            ThreadStart start = new ThreadStart(objCreateWork.ProcessQuickPLan);
            new Thread(start).Start();
        }
        Console.ReadLine();
    }
}

class CreateWork
{
    private object CurrentSession = -1;
    public void ProcessQuickPLan()
    {
        lock (CurrentSession)
        {
            CurrentSession = ThreadManager.CurrentSession;
            Console.WriteLine(CurrentSession);
            ThreadManager.CurrentSession = Convert.ToInt32(ThreadManager.CurrentSession) + 1;
        }
    }
}

class ThreadManager
{
    public static object CurrentSession
    {
        get;
        set;
    }
}

答案 4 :(得分:0)

将您的代码更改为:

using System;
using System.Threading;
class Program
{
    static void Main(string[] args)
    {
        ThreadManager.CurrentSession = 0;
        for (int i = 0; i < 10; i++)
        {
            CreateWork objCreateWork = new CreateWork();
            ThreadStart start = new ThreadStart(objCreateWork.ProcessQuickPLan);
            new Thread(start).Start();
        }
        Console.ReadLine();
    }
}

class CreateWork
{
    private static object _lock = new Object();

    public void ProcessQuickPLan()
    {
        lock (_lock)
        {            
            Console.WriteLine(ThreadManager.CurrentSession);
            ThreadManager.CurrentSession++;
        }
    }
}

class ThreadManager
{
    public static int CurrentSession
    {
        get;
        set;
    }
}

重要的是你的锁和跟踪你的身份之间的分离。

私有锁是一个静态对象,因此它在线程之间共享。我还删除了每次为锁指定一个新值。