Optional thread safety (thread safe section only under condition) - c#

As stated in the title i have this situation
lock ( _myLockObj )
{
// protected section here ( select + update over SQL Tables)
}
That works great , but sometimes i do not need thread safety , because is guaranteed by datas that nothing wrong could happen (even if two thread run in parralel) but i need speed .
At the moment program can understand when threads could have threads safety problem and when not ( and when not i need to be fast as possible ) .
What i would achieve make is optionallity on that lock instruction , so that it become effective only if in proper condition is true .
eg :
lock ( _myLockObj ) && flag
I am pretty sure that lock keyword does not provide that semantics, what i would understand is what is the proper way to achieve that behavior.

The lock statement is a syntactic sugar for Monitor.Enter + Monitor.Exit in a try/finally block.
You can use these methods directly:
bool flag = false;
bool acquiredLock = false;
try
{
if (flag)
{
Monitor.Enter(_myLockObj, ref acquiredLock);
}
}
finally
{
if (flag & acquiredLock)
{
Monitor.Exit(_myLockObj);
}
}

Personally I think the following is nicer:
private bool flag;
public T DoStuff() {
T DoStuffUnsafe() {
// ...
}
if (flag) {
lock (_myLockObj) {
return DoStuffUnsafe();
}
}
else {
return DoStuffUnsafe();
}
}

Related

c# lock function during async file write [duplicate]

I want to start some new threads each for one repeating operation. But when such an operation is already in progress, I want to discard the current task. In my scenario I need very current data only - dropped data is not an issue.
In the MSDN I found the Mutex class but as I understand it, it waits for its turn, blocking the current thread. Also I want to ask you: Does something exist in the .NET framework already, that does the following:
Is some method M already being executed?
If so, return (and let me increase some counter for statistics)
If not, start method M in a new thread
The lock(someObject) statement, which you may have come across, is syntactic sugar around Monitor.Enter and Monitor.Exit.
However, if you use the monitor in this more verbose way, you can also use Monitor.TryEnter which allows you to check if you'll be able to get the lock - hence checking if someone else already has it and is executing code.
So instead of this:
var lockObject = new object();
lock(lockObject)
{
// do some stuff
}
try this (option 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);
}
(you'll probably want to put a try..finally in there to ensure the lock is released)
or dispense with the explicit lock althogether and do this
(option 2)
private int _inUseCount;
public void MyMethod()
{
if (Interlocked.Increment(ref _inUseCount) == 1)
{
// do dome stuff
}
Interlocked.Decrement(ref _inUseCount);
}
[Edit: in response to your question about this]
No - don't use this to lock on. Create a privately scoped object to act as your lock.
Otherwise you have this potential problem:
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();
}
}
In the above example, some external code has managed to disrupt the internal locking of our class just by taking out a lock on something that was externally accessible.
Much better to create a private object that you control, and that no-one outside your class has access to, to avoid these sort of problems; this includes not using this or the type itself typeof(MyClassWithLockInside) for locking.
One option would be to work with a reentrancy sentinel:
You could define an int field (initialize with 0) and update it via Interlocked.Increment on entering the method and only proceed if it is 1. At the end just do a Interlocked.Decrement.
Another option:
From your description it seems that you have a Producer-Consumer-Scenario...
For this case it might be helpful to use something like BlockingCollection as it is thread-safe and mostly lock-free...
Another option would be to use ConcurrentQueue or ConcurrentStack...
You might find some useful information on the following site (the PDf is also downlaodable - recently downloaded it myself). The Adavnced threading Suspend and Resume or Aborting chapters maybe what you are inetrested in.
You should use Interlocked class atomic operations - for best performance - since you won't actually use system-level sychronizations(any "standard" primitive needs it, and involve system call overhead).
//simple non-reentrant mutex without ownership, easy to remake to support //these features(just set owner after acquiring lock(compare Thread reference with Thread.CurrentThread for example), and check for matching identity, add counter for reentrancy)
//can't use bool because it's not supported by CompareExchange
private int lock;
public bool TryLock()
{
//if (Interlocked.Increment(ref _inUseCount) == 1)
//that kind of code is buggy - since counter can change between increment return and
//condition check - increment is atomic, this if - isn't.
//Use CompareExchange instead
//checks if 0 then changes to 1 atomically, returns original value
//return true if thread succesfully occupied lock
return CompareExchange(ref lock, 1, 0)==0;
return false;
}
public bool Release()
{
//returns true if lock was occupied; false if it was free already
return CompareExchange(ref lock, 0, 1)==1;
}

Conditionally Use Lock in the Thread?

I have a method which is being used by multi-thread. In the method, there are some critical codes that I have to use lock to allow only ONE thread to access it. So, the code looks like:
private void RunCode()
{
...... // some other codes
lock (myLock)
{
...... // critical code01
}
...... // some other codes
lock (myLock)
{
...... // critical code02
}
....... // some other codes
}
This code is being used by multi-thread. Now, because of some workflow changes, we want to keep the code run as it is, BUT in some special cases, we want to run the critical codes immediately without the lock. We are ok even if the calculation result is not 100% correct because we do not lock it. So, the code should look like:
private void RunCode(bool isSpecial)
{
...... // some other codes
lock (myLock) // if isSpecial == true, do not lock it, otherwise, lock it
{
...... // critical code01
}
...... // some other codes
lock (myLock) // if isSpecial == true, do not lock it, otherwise, lock it
{
...... // critical code02
}
....... // some other codes
}
Based on research, it seems we have to do something like
if (isSpecial)
{
...... // critical code01
}
else
{
lock (myLock)
{
...... // critical code01
}
}
It will work, but the issue is that we have to repeat the critical code01 (and code02) twice. And these codes are pretty complex and closely related with other codes in the RunCode() method.
My question is: is there a better way to do this? Any suggestions? We are using c# .net, but any suggestions are welcome.
Thanks
Try use a Monitor class directly. It has a method TryEnter
Rewrite your code like this:
try
{
if (isSpecialCase || Monitor.TryEnter(myLock, TimeSpan.MaxValue))
{
// critical code01
}
}
finally
{
if (!isSpecialCase)
{
// lock was taken
Monitor.Exit(myLock);
}
}
What you want to do sounds pretty strange to say the least. But if I could not live without it, I would try defining a lambda expression on the fly and call that in these two locations. Something along the lines of
int aNumber = 5;
Action criticalCode01 = () => {Console.WriteLine("Foo! (repeat "+aNumber+" times)");};
if (isSpecial)
{
criticalCode01();
}
else
{
lock (myLock)
{
criticalCode01();
}
}
This is what you are looking for:
try
{
if (!isSpecialCase) Monitor.Enter(myLock);
// critical code01
}
finally
{
if (!isSpecialCase) Monitor.Exit(myLock);
}

C# Enqueue Failure

I have a simple logging mechanism that should be thread safe. It works most of the time, but every now and then I get an exception on this line, "_logQ.Enqueue(s);" that the queue is not long enough. Looking in the debugger there are sometimes just hundreds of items, so I can't see it being resources. The queue is supposed to expand as needed. If I catch the exception as opposed to letting the debugger pause at the exception I see the same error. Is there something not thread safe here? I don't even know how to start debugging this.
static void ProcessLogQ(object state)
{
try
{
while (_logQ.Count > 0)
{
var s = _logQ.Dequeue();
string dir="";
Type t=Type.GetType("Mono.Runtime");
if (t!=null)
{
dir ="/var/log";
}else
{
dir = #"c:\log";
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
}
if (Directory.Exists(dir))
{
File.AppendAllText(Path.Combine(dir, "admin.log"), DateTime.Now.ToString("hh:mm:ss ") + s + Environment.NewLine);
}
}
}
catch (Exception)
{
}
finally
{
_isProcessingLogQ = false;
}
}
public static void Log(string s) {
if (_logQ == null)
_logQ = new Queue<string> { };
lock (_logQ)
_logQ.Enqueue(s);
if (!_isProcessingLogQ) {
_isProcessingLogQ = true;
ThreadPool.QueueUserWorkItem(ProcessLogQ);
}
}
Note that the threads all call Log(string s). ProcessLogQ is private to the logger class.
* Edit *
I made a mistake in not mentioning that this is in a .NET 3.5 environment, therefore I can't use Task or ConcurrentQueue. I am working on fixes for the current example within .NET 3.5 constraints.
** Edit *
I believe I have a thread-safe version for .NET 3.5 listed below. I start the logger thread once from a single thread at program start, so there is only one thread running to log to the file (t is a static Thread):
static void ProcessLogQ()
{
while (true) {
try {
lock (_logQ);
while (_logQ.Count > 0) {
var s = _logQ.Dequeue ();
string dir = "../../log";
if (!Directory.Exists (dir))
Directory.CreateDirectory (dir);
if (Directory.Exists (dir)) {
File.AppendAllText (Path.Combine (dir, "s3ol.log"), DateTime.Now.ToString ("hh:mm:ss ") + s + Environment.NewLine);
}
}
} catch (Exception ex) {
Console.WriteLine (ex.Message);
} finally {
}
Thread.Sleep (1000);
}
}
public static void startLogger(){
lock (t) {
if (t.ThreadState != ThreadState.Running)
t.Start ();
}
}
private static void multiThreadLog(string msg){
lock (_logQ)
_logQ.Enqueue(msg);
}
Look at the TaskParallel Library. All the hard work is already done for you. If you're doing this to learn about multithreading read up on locking techniques and pros and cons of each.
Further, you're checking if _logQ is null outside your lock statement, from what I can deduce it's a static field that you're not initializing inside a static constructor. You can avoid doing this null check (which should be inside a lock, it's critical code!) you can ensure thread-safety by making it a static readonly and initializing it inside the static constructor.
Further, you're not properly handling queue states. Since there's no lock during the check of the queue count it could vary on every iteration. You're missing a lock as your dequeuing items.
Excellent resource:
http://www.yoda.arachsys.com/csharp/threads/
For a thread-safe queue, you should use the ConcurrentQueue instead:
https://msdn.microsoft.com/en-us/library/dd267265(v=vs.110).aspx

Monitor.TryEnter / Monitor.Exit and SynchronizationLockException

Is it possible to detect if the same thread trying to release the lock?
We have many places in code that looks like:
try
{
try
{
if(!Monitor.TryEnter(obj, 2000))
{
throw new Exception("can not lock");
}
}
finally
{
Monitor.Exit(obj);
}
}
catch
{
//Log
}
The above code very simplified, and actually Enter and Exit statement located in custom object (lock manager).
The problem, that in that structure, we have SynchronizationLockException when trying to "Exit", since it looks like the thread that not succeed to lock, tries to release in finally.
So the question, is how I can know if the thread who making Monitor.Exit is the same thread who did Monitor.Enter?
I thought that I can use CurrentThread.Id to sync enter and exit, but I'm not sure if it "safe" enough.
So the question, is how I can know if the thread who making Monitor.Exit is the same thread who did Monitor.Enter?
You can't, easily, as far as I'm aware. You can't find out which thread owns a monitor.
However, this is just a coding issue - you should change your code so that it doesn't even attempt to release the monitor when it shouldn't. So your code above could be rewritten as:
if (!Monitor.TryEnter(obj, 2000))
{
throw new Exception(...);
}
try
{
// Presumably other code
}
finally
{
Monitor.Exit(obj);
}
Or even better, if you're using .NET 4, use the overload of TryEnter which accepts an ret parameter:
bool gotMonitor = false;
try
{
Monitor.TryEnter(obj, ref gotMonitor);
if (!gotMonitor)
{
throw new Exception(...);
}
// Presumably other code
}
finally
{
if (gotMonitor)
{
Monitor.Exit(obj);
}
}
As you think that to put the calling of Monitor.Exit in try-catch was 'durty'(dirty?), here's a very simple idea trying to 'take the durty away'. Lock is reentrant for the same thread and if one thread acquired successfully, before it releases, attempt from another thread will fail. So that you can consider something like:
public void Exit(object key) {
if(!IsActive) {
return;
}
if(LockDictionary.ContainsKey(key)) {
var syncObject=LockDictionary[key];
if(Monitor.TryEnter(syncObject.SyncObject, 0)) {
SetLockExit(syncObject);
Monitor.Exit(syncObject.SyncObject);
Monitor.Exit(syncObject.SyncObject);
}
}
}
We call Monitor.Exit twice because we lock it twice, one in the code outer, and one just here.
I know this is an older question, but here's my answer anyway.
I would move the try-finally construct inside the if:
try
{
if(Monitor.TryEnter(obj, 2000))
{
try
{
// code here
}
finally
{
Monitor.Exit(obj);
}
}
else
{
throw new Exception("Can't acquire lock");
}
}
catch
{
// log
}

Can I stop a System.Threading.Timer

I have an application that uses timers to occasionally run monitoring tasks on secondary threads. Some of these cleanup tasks take a lot of time and I would like to be able to abort these tasks (gracefully if possible) when my user ends the program.
Is there any way to abort the thread programatically as I can with Thread.Abort(), or would I have to add a flag to the code to indicate that the thread has finished and check for that in valrious places in the code that is started by the timer?
You can stop the timer before it's callback executes using .change, but once the callback starts executing you should use an application level flag to allow your code to exit.
As a side note, you shouldn't use thread.abort() unless you are absolutely 100% sure that you know the state it is going to be left in. it can seriously destabilize your application in strange ways.
There is no way to know the Thread on which a Threading.Timer callback will run ahead of time. Hence there is no general way to abort it. It is possible to have the callback itself communicate the Thread instance but it opens up a couple of race conditions
Note: In general using Abort is a bad practice. It's a fairly reliable way to end up with hard to detect deadlocks and / or resource leaks. It's much better to use a passive mechanism like CancellationToken
use this.Timer.Change(Timeout.Infinite, Timeout.Infinite);
first i have use .dispose method but it does not work in my case so i have use Timer.change.
this is the best solution i have find.
You mean something along these lines?
using System;
using System.Threading ;
class AppCore : IDisposable
{
Timer TimerInstance ;
string[] Args ;
public AppCore( string[] args )
{
if ( args == null ) throw new ArgumentNullException("args") ;
this.TimerInstance = new Timer( Tick , null , new TimeSpan(0,0,30) , new TimeSpan(0,0,15) ) ;
this.Args = args ;
this.Cancelled = false ;
this.Disposed = false ;
return ;
}
public int Run()
{
// do something useful
return 0 ;
}
private bool Cancelled ;
public void Cancel()
{
lock( TimerInstance )
{
Cancelled = true ;
TimerInstance.Change( System.Threading.Timeout.Infinite , System.Threading.Timeout.Infinite ) ;
}
return ;
}
private void Tick( object state )
{
if ( !Cancelled )
{
// do something on each tick
}
return ;
}
private bool Disposed ;
public void Dispose()
{
lock ( TimerInstance )
{
if ( !Disposed )
{
using ( WaitHandle handle = new EventWaitHandle( false , EventResetMode.ManualReset ) )
{
TimerInstance.Dispose( handle ) ;
handle.WaitOne() ;
}
Disposed = true ;
}
}
return ;
}
}
public void stopTimer(){
myThreadingTimer = null;
}
Explication: Destroy object = destroy proccess.

Categories

Resources