Reputation: 821
While code reviewing myself work, I spotted a very interesting piece of code where I can swear it would cause a deadlock, but I've tested it many times, with multiple threads, and could not get any.
it's puzzling me so hard that I decided to ask it here.
So the assumption is that the LOCK doesn't lock for the same thread, but I would like to confirm it.
Following the piece of code
public class SplitService : ISplitService
{
private IRecordService recordService;
public SplitService(IRecordService recordService)
{
this.recordService = recordService;
}
private ConcurrentQueue<Batch> _batches = new ConcurrentQueue<Batch>();
public void Feed(Something r)
{
lock (this.recordService)
{
if (!this.recordService.CanAppend(r))
{
Flush();
}
this.recordService.Append(r);
}
}
public void Flush()
{
lock (this.recordService)
{
if (!this.recordService.Any()) return;
var record = this.recordService.GetBatch();
_batches.Enqueue(record);
this.recordService.Clean();
}
}
public IEnumerable<Batch> Get()
{
while (_batches.Any())
{
if (_batches.TryDequeue(out Batch batch))
{
yield return batch;
}
}
}
}
As you can notice, the method Feed
locks into a object, and if the same returns false for CanAppend it call the Flush
method that also try to lock the same object.
So I would expect a deadlock there
Extrapolating a bit after understanding it, as Lock is recursive, we can assume that this will also work:
lock(locker){
Console.WriteLine("Hello World");
await new Task(() => {
lock(locker){
Console.WriteLine("Hello World from locker");
}
});
}
Upvotes: 2
Views: 123
Reputation: 62472
Monitor
objects is C# are recursive, so you just have to remember to unlock them as many times as you lock them. For example, this is perfectly valid:
lock(someObject)
{
lock(someObject)
{
lock(someObject)
{
Consolw.WriteLine("hello world")
}
}
}
It's important to realize that lock is only recursive once you've acquired the lock. If thread A has acquired the lock and then thread B tries to acquire the lock then B will block until thread A releases the lock.
Upvotes: 6
Reputation: 213
For a deadlock, you need 2 accessors and 2 resources. In this case there's only one resource, so everyone will wait patiently for it.
Upvotes: 3