In Term 4 Week 2, I was busy on preparing for physics presentation. However, I also followed up my plan, that is to finish my code comment and started writing my documentation and presentation slides.
Progress
School work
I wrote code comments for each part of my project. They are really detailed and explained the purposes of these codes.




C#
Meanwhile, I was playing around C# again… And this time I need to have a concurrent lock to ensure some operations can be ran safely (just like using Interlocked
to perform atomic level value type operations to ensure the value is safe in high concurrency usage).
Traditionally we use lock
, this can lock an object, and when the internal operation is done, the object will be released. While the object is locked, any operations that visits this object will be forced to wait until it is released.
The lock
kinda meet the guideline of what I need, however, my current project requires to execute a same function more than 1000 times (or even 10000+) times at the same millisecond, and lock
has a bad performance.
1 | ```csharp |
as we can observe, using SpinLock
requires declaring a boolean variable to be te placeholder of the lock, and we need to use try-finally
to ensure the lock has been taken and unlocked. It is too long to write and we need to declare lots of temporary boolean variables.
So I digged inside SpinLock’s source code. It used SpinWait
to spin and to block the thread to approach the waiting. And it used Interlocked
to declare a placeholder that represents this lock has been locked or not.
Hence, I made my own lock
:
1 | public class Lock : IDisposable |
- I declared a int field represents whether or not the lock has been taken (with locked = 1 and unlocked = 0)
- When requests
EnterLock
, it will create a new SpinWait and to keep spining while the lock is locked (usingInterlocked
to approach atomic level lock-unlock operation) - If the lock is unlocked, and the
EnterLock
is proccessing, it will compare the_locked
field to 0, if it is 0 (unlocked), then exchange it to 1 (locked), and return itself to end the execution (returning itself is required for the future implemetation) - If the lock is locked, then spin it once (with param 10, default this is 20, which spins slightly faster now)
- We need to unlock the lock, therefore we have function
ExitLock
, and it exchanges_locked
from locked (1) to unlocked (0) - We also implemented IDisposable interface, and in the
Dispose
function, we usedExitLock
This is a lightweighted and high performanced lock, we can use it with two ways:
- Manually control Enter and Exit
1
2
3
4
5
6
7public Lock _lock = new Lock();
public void MyConcurrentLogic()
{
_lock.EnterLock();
//my logic that should not be processed at the same time
_lock.ExitLock();
} - Automatically Exit (recommend with returning functions)
1
2
3
4
5
6
7
8
9public Lock _lock = new Lock();
public int MyConcurrentCalculation()
{
using(_lock.EnterLock())
{
//my logic that should not be processed at the same time
return xxx;
}
}
We need to use
Dispose
fromIDisposable
to approach the coding style in method 2, and we need to return the lock itself to ensure it can be “disposed” (acutally exit lock) after the internal code finishes executing.
Challenges
There were no challenges this week.
Reflection
This week, I was quite efficient, I used my time wisely and sufficiently. I finished what I planeed to do, and I used my time in class to help me with the stuffs I was up to as well. I think I did well overall.
Timeline
This week I finished my code comment, and I’m still on track with my plan. Next week I will start finishing my documentation and hopefully the slides.