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
答案 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;
}
}
}
答案 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;
}
}
重要的是你的锁和跟踪你的身份之间的分离。
私有锁是一个静态对象,因此它在线程之间共享。我还删除了每次为锁指定一个新值。