2023-06-06 16:02:42 +02:00
include::../why-dotnet.adoc[]
2023-05-03 11:06:20 +02:00
2023-06-06 16:02:42 +02:00
== How to fix it
2021-12-02 14:29:24 +01:00
2023-06-06 16:02:42 +02:00
To make sure that a lock is always released correctly, you can follow one of these two methods:
2021-12-02 14:29:24 +01:00
2023-06-06 16:02:42 +02:00
* Use a https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/lock[`lock`] statement with your lock object.
* Use a https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/exception-handling-statements#the-try-finally-statement[`try-finally`] statement and put the release of your lock object within the finally block.
=== Code examples
==== Noncompliant code example
[source,csharp,diff-id=1,diff-type=noncompliant]
2023-05-25 14:18:12 +02:00
----
2023-06-12 10:24:02 +02:00
class MyClass
2023-05-25 14:18:12 +02:00
{
private object obj = new object();
2023-06-12 10:24:02 +02:00
public void DoSomethingWithMonitor()
2023-05-25 14:18:12 +02:00
{
2023-06-06 16:02:42 +02:00
Monitor.Enter(obj); // Noncompliant: not all paths release the lock
2023-05-25 14:18:12 +02:00
if (IsInitialized())
{
// ...
Monitor.Exit(obj);
}
}
2023-06-06 16:02:42 +02:00
}
----
2023-05-25 14:18:12 +02:00
2023-06-06 16:02:42 +02:00
[source,csharp,diff-id=2,diff-type=noncompliant]
----
2023-06-12 10:24:02 +02:00
class MyClass
2023-06-06 16:02:42 +02:00
{
2023-05-25 14:18:12 +02:00
private ReaderWriterLockSlim lockObj = new ReaderWriterLockSlim();
2023-06-12 10:24:02 +02:00
public void DoSomethingWithReaderWriteLockSlim()
2023-05-25 14:18:12 +02:00
{
2023-06-06 16:02:42 +02:00
lockObj.EnterReadLock(); // Noncompliant: not all paths release the lock
2023-05-25 14:18:12 +02:00
if (IsInitialized())
{
// ...
lockObj.ExitReadLock();
}
}
}
----
2023-06-06 16:02:42 +02:00
==== Compliant solution
2023-05-25 14:18:12 +02:00
2023-06-12 10:24:02 +02:00
[source,csharp,diff-id=1,diff-type=compliant]
2023-05-25 14:18:12 +02:00
----
2023-06-12 10:24:02 +02:00
class MyClass
2023-05-25 14:18:12 +02:00
{
private object obj = new object();
2023-06-12 10:24:02 +02:00
public void DoSomethingWithMonitor()
2023-05-25 14:18:12 +02:00
{
2023-06-07 15:41:34 +02:00
lock(obj) // Compliant: the lock will be released at the end of the lock block
2023-05-25 14:18:12 +02:00
{
if (IsInitialized())
{
2023-06-06 16:02:42 +02:00
// ...
2023-05-25 14:18:12 +02:00
}
}
}
2023-06-06 16:02:42 +02:00
}
----
2023-05-25 14:18:12 +02:00
2023-06-12 10:24:02 +02:00
[source,csharp,diff-id=2,diff-type=compliant]
2023-06-06 16:02:42 +02:00
----
2023-06-12 10:24:02 +02:00
class MyClass
2023-06-06 16:02:42 +02:00
{
2023-05-25 14:18:12 +02:00
private ReaderWriterLockSlim lockObj = new ReaderWriterLockSlim();
2023-06-12 10:24:02 +02:00
public void DoSomethingWithReaderWriteLockSlim()
2023-05-25 14:18:12 +02:00
{
2023-06-07 15:41:34 +02:00
lockObj.EnterReadLock(); // Compliant: the lock will be released in the finally block
2023-05-25 14:18:12 +02:00
try
{
if (IsInitialized())
{
2023-06-06 16:02:42 +02:00
// ...
2023-05-25 14:18:12 +02:00
}
}
finally
{
lockObj.ExitReadLock();
}
}
}
----
2023-06-06 16:02:42 +02:00
include::../resources-dotnet.adoc[]
2023-05-25 14:18:12 +02:00
2023-06-06 16:02:42 +02:00
* https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/lock[`lock` statement]
* https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/exception-handling-statements#the-try-finally-statement[The `try-finally` statement]
2021-06-02 20:44:38 +02:00
2023-06-06 16:02:42 +02:00
include::../rspecator.adoc[]