SemaphorefullException - 逻辑错误引发?
我有一个多线程应用程序,其中一个类使用信号量来控制读取和读取。写作。这似乎在大多数情况下工作正常,但是我抛出了一些莫名其妙的信号量异常,这表明我正在尝试在不应该释放的时候释放。问题是我已经检查了我的代码&似乎无法找到导致这种情况发生的逻辑缺陷。
如果有人可以看一下下面的示例代码,我将非常感激让我知道我哪里出了问题,因为在这个阶段我想我开始发疯了..
请注意,“真正的”代码不仅有一个线程循环,而且它非常接近
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
{
Thread t = new Thread(() => ThreadA());
t.Start();
}
}
/// <summary>
/// Run the methods in the worker class
/// </summary>
private static void ThreadA()
{
Token token = null;
WorkClass workClass = new WorkClass();
try
{
workClass.BeginRead(out token, "A");
}
finally
{
workClass.EndRead(token);
}
}
}
/// <summary>
/// this class does the actual work
/// </summary>
public class WorkClass
{
private Semaphore _pool = new Semaphore(2, 2);
public void BeginRead(out Token token, string s)
{
Semaphore sem = null;
try
{
// wait for the main semaphore to signal
_pool.WaitOne();
// set local semaphore equal to main
sem = _pool;
//simulate work
Thread.Sleep(100);
}
finally
{
//return the token with the semaphore
token = new Token(sem, s);
}
}
public void EndRead(Token token)
{
try
{
// do some more work
}
finally
{
// release the semaphore if not null
if (null != token.signal)
{
token.signal.Release();
}
}
}
}
public class Token
{
internal readonly Semaphore signal;
internal readonly string s;
internal Token(Semaphore _signal, string _s)
{
this.s = _s;
this.signal = _signal;
}
}
I have a multithreaded application, of which one of the classes uses a semaphore to control reading & writing. This seems to work fine most of the time, however I'm getting some inexplicable semaphorefull exceptions thrown, indicating that I'm trying to release when I shouldn't be. The problem is I've been over my code & can't seem to find a flaw in the logic which would cause this to happen.
I would be really grateful if someone could take a look at the sample code below & let me know where I'm going wrong as at this stage I think I'm beginning to go mad..
Please note that the "real" code doesn't just have a loop of threads but its pretty close
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
{
Thread t = new Thread(() => ThreadA());
t.Start();
}
}
/// <summary>
/// Run the methods in the worker class
/// </summary>
private static void ThreadA()
{
Token token = null;
WorkClass workClass = new WorkClass();
try
{
workClass.BeginRead(out token, "A");
}
finally
{
workClass.EndRead(token);
}
}
}
/// <summary>
/// this class does the actual work
/// </summary>
public class WorkClass
{
private Semaphore _pool = new Semaphore(2, 2);
public void BeginRead(out Token token, string s)
{
Semaphore sem = null;
try
{
// wait for the main semaphore to signal
_pool.WaitOne();
// set local semaphore equal to main
sem = _pool;
//simulate work
Thread.Sleep(100);
}
finally
{
//return the token with the semaphore
token = new Token(sem, s);
}
}
public void EndRead(Token token)
{
try
{
// do some more work
}
finally
{
// release the semaphore if not null
if (null != token.signal)
{
token.signal.Release();
}
}
}
}
public class Token
{
internal readonly Semaphore signal;
internal readonly string s;
internal Token(Semaphore _signal, string _s)
{
this.s = _s;
this.signal = _signal;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
Semaphore
通过 WaitHandle - 当您的WorkerClass
Dispose
本身是Dispose
-d 时,您需要将其设置为Dispose
。也许由于未处理的信号量实例,您在负载下达到了某些系统限制?这可能不是问题,但它是问题,无论您如何重新设计
池
静态或其他单例机制。Semaphore
isIDisposable
through WaitHandle - you need to make yourWorkerClass
Dispose
it when it'sDispose
-d of itself.Perhaps you are hitting some system limit under load due to unDisposed Semaphore instances? This may not be THE problem but it is A problem, regardless of any redesign you do to make
pool
static, or other singleton mechanism.事实上,您在工作类之外传递信号量(包装在
Token
实例中)可能表明您正在其他地方使用它,除了BeginRead
和>结束阅读
。如果信号量仅在
WorkClass
内部使用,我强烈建议将其从Token
中完全删除 - 将其设为私有静态字段(如 吉姆指出)并向世界其他地方隐藏它。The fact that you are passing the semaphore outside of your worker class (wrapped in a
Token
instance) may indicate that you are using it somewhere else, other thatBeginRead
andEndRead
.If semaphore is used only inside the
WorkClass
, I would strongly recommend removing it from theToken
completely - make it a private static field (as Jim pointed out) and hide it from the rest of the world.您将在这里遇到的一个问题是,您正在为
WorkClass
的每个实例创建一个新信号量。因此,如果您有三个WorkClass
实例,则会有三个独立的信号量。我认为您希望信号量是静态的,以便所有实例共享一个信号量。您将其称为_pool
,因此我假设您希望所有实例访问的共享资源数量有限。我不明白您在问题中提供的代码如何抛出
SemaphoreFullException
。您确定您发布的代码在功能上与您遇到问题的代码相同吗?如果您编译并运行您发布的代码,您会遇到该异常吗?One problem you're going to run into here is that you're creating a new semaphore for each instance of the
WorkClass
. So if you have threeWorkClass
instances, there will be three separate semaphores. I think you want your semaphore to bestatic
, so that all instances share the one semaphore. You call it_pool
, so I assume there's a limited number of shared resources that you want all instances to access.I don't see how the code you presented in your question can throw a
SemaphoreFullException
. Are you certain that the code you posted is functionally equivalent to the code that you're having trouble with? If you compile and run the code that you posted, do you get that exception?