3

使用lock 语句,可以“确保一个线程不进入代码的临界区,而另一个线程处于临界区。如果另一个线程试图进入锁定的代码,它将等待、阻塞,直到对象被释放。”

如果我想要的行为是,如果另一个线程尝试进入锁定的代码,它会跳过整个代码(而不是等待锁被释放)怎么办?我想到的一个想法是使用标志,例如

if(flag) return;
flag = true;
//do stuff here
flag =false;

但我知道这是不安全的,因为两个线程可以在任何人设置为 true 之前通过第一行,或者在异常情况下标志永远不会设置为 false。你能提出改进或替代方案吗?

4

3 回答 3

5

使用这个重载Monitor.TryEnter它可以让你指定一个超时。

在指定的时间内尝试获取指定对象的排他锁。

返回值 类型:System.Boolean 如果当前线程在没有阻塞的情况下获得锁,则为 true;否则为 true。否则为假。

在您的情况下,您可能希望使用接近 TimeSpan.Zero.

如果您不希望尝试获取锁的线程等待任何时间长度,您可以只重载of Monitor.TryEnter,它不接受TimeSpan参数。此方法将立即返回而无需等待 - 非常接近您尝试使用的标志技术的情绪。

于 2011-12-28T05:32:02.287 回答
1

您需要限制为 1 且超时时间为 0 毫秒的信号量

通过使用 Semaphore,您可以说一次只有有限数量的线程可以访问一段代码。

请参阅此示例以了解如何使用它

您需要使用此方法等待

bool WaitOne(int millisecondsTimeout)

指定超时时间 = 0;这样,您的等待线程将等待 0 秒,这意味着它们将简单地跳过代码

例子

class SemaphoreExample    
{ 
// Three reserved slots for threads
public static Semaphore Pool = new Semaphore(1, 0);

public static void Main(string[] args) 
{    
// Create and start 20 threads    
for (int i = 0; i < 20; i++) 
{ 
    Thread t = new Thread(new ThreadStart(DoWork)); 
    t.Start(); 
}

Console.ReadLine();    
}

private static void DoWork()    
{    
// Wait 0 miliseconds  
SemaphoreExample.Pool.WaitOne(0);


#region Area Protected By Semaphore    
Console.WriteLine("Acquired slot...");

for (int i = 0; i < 10; i++) 
{   
    Console.WriteLine(i + 1);  
}   
Console.WriteLine("Released slot...");    

#endregion        
// Release the semaphore slot    
SemaphoreExample.Pool.Release();    
}    
}
于 2011-12-28T05:30:27.360 回答
0

你可以使用 Monitor.TryEnter

http://msdn.microsoft.com/en-us/library/dd289679.aspx

于 2011-12-28T05:43:06.977 回答