C# 每次将代码段锁定到一个入口
我试图限制对单音对象的访问,因此只有一个线程 使用它的时候,而且,我想防止同一线程访问两次 到限制代码 我尝试了锁定方法,发现锁定她的线程不是锁定的,而是其他线程 详情如下:C# 每次将代码段锁定到一个入口,c#,multithreading,synchronization,locking,C#,Multithreading,Synchronization,Locking,我试图限制对单音对象的访问,因此只有一个线程 使用它的时候,而且,我想防止同一线程访问两次 到限制代码 我尝试了锁定方法,发现锁定她的线程不是锁定的,而是其他线程 详情如下: public sealed class Singleton { private static readonly Singleton instance = new Singleton(); static Singleton() { } private Singleton()
public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();
static Singleton()
{
}
private Singleton()
{
}
public static Singleton Instance
{
get
{
return instance;
}
}
}
public class SomeWorker
{
private readonly Timer _doWorkTimer = new Timer(20);
public SomeWorker()
{
InitiateTimer();
}
private void InitiateTimer()
{
_doWorkTimer .Elapsed += DoWorkElapse;
_doWorkTimer .Enabled = true;
}
private void DoWorkElapse(object source, ElapsedEventArgs e)
{
DoSomeWork();
}
private void DoSomeWork()
{
// I know that lock on string is wrong!
// Its just for the example only I
// Its just to make sure all the program is use the same lock..
lock ("ConnectionLock")
{
Console.WriteLine("Lock");
var inst = Singletone.Instance;
// Do Some Work on "inst" ...
Console.WriteLine("Unlock");
}
}
}
例如,控制台中的结果是:
。
.
锁
解锁
锁定
锁定
解锁
。
.
正如我们所看到的,两个锁注释一个接一个地显示
这意味着“DoSomeWork()”被计时器线程访问了两次
有人知道怎么锁吗
还有其他同步方法吗
thanx.您没有正确锁定(最重要的是,您正在锁定一个字符串,这是一个很大的禁忌)。为了节省时间,请阅读Jon Skeet的文章,并实施其中一种模式以避免头痛。您没有正确地进行锁定(最重要的是,您正在锁定一个字符串,这是一个很大的禁忌)。为了节省时间,请阅读Jon Skeet的文章,并实现其中一种模式以避免您的头痛。在您的代码中
public static Singletone Instance()
{
if (_instance == null)
{
lock (_instance)
{
if (_instance == null)
{
_instance = new Singletone ();
}
}
}
return _instance;;
}
想想看<代码>如果(\u实例==null)您执行了锁定(\u实例)
。因此,您可以使用null
锁定。那一点也不好
在MSDN中,如何使用lock
的示例如下:
class Account
{
decimal balance;
private Object thisLock = new Object();
public void Withdraw(decimal amount)
{
lock (thisLock)
{
if (amount > balance)
{
throw new Exception("Insufficient funds");
}
balance -= amount;
}
}
}
我想你应该遵循它,并有一个单独的对象使用它作为锁
其次,原语用于区分不同线程对共享资源的访问。如果需要将访问与一个线程分开,只需使用标志。大概是这样的:
bool isBusy = false;
public static void Foo()
{
if (!isBusy)
{
isBusy = true;
try
{
//do the job
}
finally
{
isBusy = false;
}
}
}
在这里,您应该理解,您只需跳过“由标志锁定”代码。相反,如果您想让线程等待自己,特别是在多线程应用程序中,我想它应该重新设计
public static Singletone Instance()
{
if (_instance == null)
{
lock (_instance)
{
if (_instance == null)
{
_instance = new Singletone ();
}
}
}
return _instance;;
}
想想看<代码>如果(\u实例==null)您执行了锁定(\u实例)
。因此,您可以使用null
锁定。那一点也不好
在MSDN中,如何使用lock
的示例如下:
class Account
{
decimal balance;
private Object thisLock = new Object();
public void Withdraw(decimal amount)
{
lock (thisLock)
{
if (amount > balance)
{
throw new Exception("Insufficient funds");
}
balance -= amount;
}
}
}
我想你应该遵循它,并有一个单独的对象使用它作为锁
其次,原语用于区分不同线程对共享资源的访问。如果需要将访问与一个线程分开,只需使用标志。大概是这样的:
bool isBusy = false;
public static void Foo()
{
if (!isBusy)
{
isBusy = true;
try
{
//do the job
}
finally
{
isBusy = false;
}
}
}
在这里,您应该理解,您只需跳过“由标志锁定”代码。相反,如果您想让线程等待自己,特别是在多线程应用程序中,我想它应该重新设计。在.NET中实现单例的最简单方法是:
public class Singleton : IDisposable
{
private readonly static Singleton _instance = new Singleton();
private readonly static object lockObject = new object();
static Singleton()
{
}
private Singleton()
{
InitiateConnection();
}
public static Singleton Instance
{
get { return _instance; }
}
/// <summary>
/// Method that accesses the DB.
/// </summary>
public void DoWork()
{
lock (lockObject)
{
//Do Db work here. Only one thread can execute these commands at a time.
}
}
~Singleton()
{
//Close the connection to DB.
//You don't want to make your singleton class implement IDisposable because
//you don't want to allow a call to Singleton.Instance.Dispose().
}
}
公共类单例:IDisposable
{
私有只读静态单例_instance=new Singleton();
私有只读静态对象lockObject=新对象();
静态单态()
{
}
私人单身人士()
{
InitiateConnection();
}
公共静态单例实例
{
获取{return\u instance;}
}
///
///方法访问数据库。
///
公共工作
{
锁定(锁定对象)
{
//在这里做Db工作。一次只有一个线程可以执行这些命令。
}
}
~Singleton()
{
//关闭与数据库的连接。
//您不想让您的单例类实现IDisposable,因为
//您不希望允许调用Singleton.Instance.Dispose()。
}
}
阅读布赖恩在回答中提出的关于这个问题的精彩文章。上述实现基于本文描述的第四个版本。CLR保证静态字段的构造是线程安全的,因此不需要在那里锁定。但是,如果对象的状态(字段)可以更改,则需要锁定
请注意,有一个
私有只读对象
用于确保DoWork
方法上的互斥。这样,单个线程可以一次调用DoWork
。还请注意,由于线程按顺序执行指令,因此同一线程不可能同时调用此方法两次。如果在DoWork
内部调用另一个最终调用DoWork
的方法,则可以从单个线程调用此方法两次。我看不出这样做有什么意义,如果这样做了,请注意避免堆栈溢出。您可以按照Konstantin的建议使用一个标志,但我认为您应该重新设计DoWork
,只做一件事,避免出现类似的情况。在.NET中实现单例的最简单方法是:
public class Singleton : IDisposable
{
private readonly static Singleton _instance = new Singleton();
private readonly static object lockObject = new object();
static Singleton()
{
}
private Singleton()
{
InitiateConnection();
}
public static Singleton Instance
{
get { return _instance; }
}
/// <summary>
/// Method that accesses the DB.
/// </summary>
public void DoWork()
{
lock (lockObject)
{
//Do Db work here. Only one thread can execute these commands at a time.
}
}
~Singleton()
{
//Close the connection to DB.
//You don't want to make your singleton class implement IDisposable because
//you don't want to allow a call to Singleton.Instance.Dispose().
}
}
公共类单例:IDisposable
{
私有只读静态单例_instance=new Singleton();
私有只读静态对象lockObject=新对象();
静态单态()
{
}
私人单身人士()
{
InitiateConnection();
}
公共静态单例实例
{
获取{return\u instance;}
}
///
///方法访问数据库。
///
公共工作
{
锁定(锁定对象)
{
//在这里做Db工作。一次只有一个线程可以执行这些命令。
}
}
~Singleton()
{
//关闭与数据库的连接。
//您不想让您的单例类实现IDisposable,因为
//您不希望允许调用Singleton.Instance.Dispose()。
}
}
阅读布赖恩在回答中提出的关于这个问题的精彩文章。上述实现基于本文描述的第四个版本。CLR保证静态字段的构造是线程安全的,因此您不需要