簡體   English   中英

鎖無法在C#中工作

[英]lock not working in C#

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)不起作用

問題出在您用來鎖定的對象上。 您正在使用實例變量,因此每個實例都有自己的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個私有靜態對象來保護資源。 初始化后切勿分配給它。

問題是你的每個線程都有自己的鎖。 使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;
        }
    }
}

這是關於ideone工作演示

我認為問題是,你將一個對象鎖定在自己的線程中,所以它永遠不會被鎖定。

更好地使用全局對象,它將被鎖定。

每個線程都包含自己的帶有鎖定器的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;
    }
}

將您的代碼更改為:

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;
    }
}

重要的是你的鎖和跟蹤你的身份之間的分離。

私有鎖是一個靜態對象,因此它在線程之間共享。 我還刪除了每次為鎖指定一個新值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM