我试图限制对单一对象的访问,因此只有一个线程 在时间使用它,此外,我想防止同一个线程访问两次 受限制的代码。
我尝试了Lock方法,我发现它的dos不会锁定锁定她的线程,只能锁定其他线程..
如下:
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");
}
}
}
控制台中的结果例如是:
。 。
锁定
解锁
锁定
锁定
解锁
。 。
正如我们所看到的,2个锁定评论一个接一个显示
所以它的意思是“DoSomeWork()”由计时器线程访问两次。
任何人都知道如何使这个锁定工作?
其他同步方法maby?
感谢名单。
答案 0 :(得分:4)
你没有正确地进行锁定(最重要的是你正在锁定一个很大的禁令)。为了节省时间,请阅读Jon Skeet撰写的this文章并实施其中一种模式以避免让您头疼。
答案 1 :(得分:1)
在您的代码中
public static Singletone Instance()
{
if (_instance == null)
{
lock (_instance)
{
if (_instance == null)
{
_instance = new Singletone ();
}
}
}
return _instance;;
}
想一想。 if (_instance == null)
你做lock (_instance)
。所以你使用null
锁定。这根本不好。
在MSDN lock Statement (C# Reference)中,如何使用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;
}
}
}
我想你应该遵循它并有一个单独的对象将它用作锁。
其次,thread syncronization原语用于分隔对不同线程的共享资源的访问。如果需要从一个线程分离访问权限,则只需使用标志。像这样:
bool isBusy = false;
public static void Foo()
{
if (!isBusy)
{
isBusy = true;
try
{
//do the job
}
finally
{
isBusy = false;
}
}
}
在这里你应该明白,你只需跳过“由旗帜锁定”的代码。相反,如果你想让线程等待自己,特别是在多线程应用程序中,我想它看起来应该重新设计。
答案 2 :(得分:0)
在.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().
}
}
阅读布莱恩在答案中提出的关于Singleton Pattern implementations in .NET的优秀文章。上述实现基于本文中描述的第四个版本。 CLR保证静态字段的构造将是线程安全的,因此您不需要在那里锁定。但是,如果对象具有可以更改的状态(字段),则需要锁定。
请注意,有一个private readonly object
用于确保DoWork
方法的互斥。这样,单个线程一次可以调用DoWork
。另请注意,由于线程按顺序执行指令,因此同一线程无法同时调用此方法两次。从单个线程调用此方法两次的唯一方法是在DoWork
内调用另一个最终调用DoWork
的方法。我无法看到这样做的重点,如果你这样做,那么请注意避免堆栈溢出。您可以按照Konstantin的建议并使用标志,但恕我直言,你应该重新设计DoWork
只做一件事,避免这样的情况。