Tuyên bố lock(someObject)
, mà bạn có thể gặp phải, là cú pháp đường xung quanh Monitor.Enter
và Monitor.Exit
.
Tuy nhiên, nếu bạn sử dụng màn hình theo cách tiết kiệm hơn này, bạn cũng có thể sử dụng Monitor.TryEnter
cho phép bạn kiểm tra xem bạn có thể nhận khóa hay không - do đó kiểm tra xem ai đó đã có và đang thực thi mã .
Vì vậy, thay vì điều này:
var lockObject = new object();
lock(lockObject)
{
// do some stuff
}
thử này (phương án 1):
int _alreadyBeingExecutedCounter;
var lockObject = new object();
if (Monitor.TryEnter(lockObject))
{
// you'll only end up here if you got the lock when you tried to get it - otherwise you'll never execute this code.
// do some stuff
//call exit to release the lock
Monitor.Exit(lockObject);
}
else
{
// didn't get the lock - someone else was executing the code above - so I don't need to do any work!
Interlocked.Increment(ref _alreadyBeingExecutedCounter);
}
(có thể bạn sẽ muốn đặt một try..finally trong đó để đảm bảo tính khóa được phát hành)
hoặc phân phối với khóa rõ ràng althogether và làm điều này
(tùy chọn 2)
private int _inUseCount;
public void MyMethod()
{
if (Interlocked.Increment(ref _inUseCount) == 1)
{
// do dome stuff
}
Interlocked.Decrement(ref _inUseCount);
}
[Edit: để đáp lại câu hỏi của bạn về this
]
Không - không sử dụng this
để lock
trên. Tạo một đối tượng có phạm vi riêng tư để hoạt động như khóa của bạn.
Nếu không, bạn có vấn đề tiềm năng này:
public class MyClassWithLockInside
{
public void MethodThatTakesLock()
{
lock(this)
{
// do some work
}
}
}
public class Consumer
{
private static MyClassWithLockInside _instance = new MyClassWithLockInside();
public void ThreadACallsThis()
{
lock(_instance)
{
// Having taken a lock on our instance of MyClassWithLockInside,
// do something long running
Thread.Sleep(6000);
}
}
public void ThreadBCallsThis()
{
// If thread B calls this while thread A is still inside the lock above,
// this method will block as it tries to get a lock on the same object
// ["this" inside the class = _instance outside]
_instance.MethodThatTakesLock();
}
}
Trong ví dụ trên, một số mã bên ngoài đã quản lý để phá vỡ các khóa nội bộ của lớp chúng tôi chỉ bằng cách lấy ra một khóa trên cái gì đó đã từ bên ngoài truy cập.
Tốt hơn hết là tạo đối tượng riêng tư mà bạn kiểm soát và không có ai ngoài lớp học của bạn có quyền truy cập, để tránh những vấn đề này; điều này bao gồm không sử dụng this
hoặc loại chính nó typeof(MyClassWithLockInside)
để khóa.
Sẽ 'this' này là một lockObject phù hợp? – DerMike
Tại sao lại là downvote? –
Được chấp nhận cho tùy chọn 2 – DerMike