C# using lock practice - c#

I have critical section in my application which contains a lot of code:
which is better way to locking access in threadMethod:
A) lock all block:
private object locker = new object();
private void threadMethod()
{
while(true)
{
lock(locker)
{
// do work - a lot of code here
}
Thread.Sleep(2000);
}
}
B) Use additional locked access member canWork:
private static object locker = new object();
private bool canWork;
private bool CanWork
{
get { lock(locker) { return this.canWork; } }
set { lock(locker) { this.canWork = value; } }
}
private void threadMethod()
{
while(true)
{
if(CanWork)
{
// do work - a lot of code here
}
Thread.Sleep(2000);
}
}
and somewhere in code
CanWork = false;

Neither is particularly good.
The first has the disadvantage that you hold the lock for a long time.
The second has the disadvantage that the state can change after you check it.
Instead try to pass immutable arguments to your method (for example a copy of the data). You will probably still need to lock for constructing the arguments and for collecting the results but this is hopefully a much shorter period of time.

The second approach will likely lead to race conditions. Can your "a lot of code" be separated in several critical/non critical chunks?

I would use the Monitor instead. Plus do you really want while(true) because this will repeat forever?
private object syncObject = new object();
private void threadMethod()
{
bool tryToRun = true;
while(tryToRun)
{
if(Monitor.TryEnter(syncObject))
{
tryToRun = false;
// do work - a lot of code here
Monitor.Exit(syncObject);
}
else
{
Thread.Sleep(2000); // Possibly knock this up the how long you expect the lock to be held for.
}
}
}

est link:
http://msdn.microsoft.com/en-us/magazine/cc188793.aspx#fig7
Best usage is
- declare a new private sync object
- use "lock(synObject) { code here ... }

Related

Avoid starting new thread with lock

Is this possible to lock method for one thread and force another to go futher rather than waiting until first thread finish? Can this problem be resolved with static thread or some proper pattern with one instance of mendtioned below service.
For presentation purposes, it can be done with static boolen like below.
public class SomeService
{
private readonly IRepository _repo;
public SomeService(IRepository repo)
{
_repo = repo;
}
private Thread threadOne;
public static bool isLocked { get; set; }
public void StartSomeMethod()
{
if(!isLocked)
{
threadOne = new Thread(SomeMethod);
isLocked = true;
}
}
public void SomeMethod()
{
while(true)
{
lots of time
}
...
isLocked = false;
}
}
I want to avoid situation when user clicked, by accident, two times to start and accidentailly second thread starts immediatelly after first finished.
You can use lock :)
object locker = new object();
void MethodToLockForAThread()
{
lock(locker)
{
//put method body here
}
}
Now the result will be that when this method is called by a thread (any thread) it puts something like flag at the beginning of lock: "STOP! You are not allowed to go any further, you must wait!" Like red light on crossroads.
When thread that called this method first, levaes the scope, then at the beginning of the scope this "red light" changes into green.
If you want to not call the method when it is already called by another thread, the only way to do this is by using bool value. For example:
object locker = new object();
bool canAccess = true;
void MethodToLockForAThread()
{
if(!canAccess)
return;
lock(locker)
{
if(!canAccess)
return;
canAccess = false;
//put method body here
canAccess = true;
}
}
Other check of canAccess in lock scope is because of what has been told on comments. No it's really thread safe. This is kind of protection that is advisible in thread safe singleton.
EDIT
After some discussion with mjwills I have to change my mind and turn more into Monitor.TryEnter. You can use it like that:
object locker = new object();
void ThreadMethod()
{
if(Monitor.TryEnter(locker, TimeSpan.FromMiliseconds(1))
{
try
{
//do the thread code
}
finally
{
Monitor.Exit(locker);
}
} else
return; //means that the lock has not been aquired
}
Now, lock could not be aquired because of some exception or because some other thread has already acuired it. In second parameter you can pass the time that a thread will wait to acquire a lock. I gave here short time because you don't want the other thread to do the job, when first is doing it.
So this solution seems the best.
When the other thread could not acquire the lock, it will go further instead of waiting (well it will wait for 1 milisecond).
Since lock is a language-specific wrapper around Monitor class, you need Monitor.TryEnter:
public class SomeService
{
private readonly object lockObject = new object();
public void StartSomeMethod()
{
if (Monitor.TryEnter(lockObject))
{
// start new thread
}
}
public void SomeMethod()
{
try
{
// ...
}
finally
{
Monitor.Exit(lockObject);
}
}
}
You can use a AutoResetEvent instead of your isLocked flag.
AutoResetEvent autoResetEvent = new AutoResetEvent(true);
public void StartSomeMethod()
{
if(autoResetEvent.WaitOne(0))
{
//start thread
}
}
public void SomeMethod()
{
try
{
//Do your work
}
finally
{
autoResetEvent.Set();
}
}

C# Set Variable in Thread

I'm trying to work with Threads for a private Project and I have a question which is, as I think very easy to answer.
Is it possible to set a variable in another thread?
Here a little Code example to show you what I'm trying to do:
public class PartyClass
{
public boolean partytime = true;
public void MakeParty()
{
while(partytime)
Console.WriteLine("I'm making a party here");
Console.WriteLine("The party ended. Please leave now");
}
public void StopParty()
{
partytime = false;
}
}
public class MainThread
{
public static int Main(String[] args)
{
PartyClass party = new PartyClass();
Thread partyThread = new Thread(new ThreadStart(party.MakeParty()));
partyThread.Start();
while (!partyThread.IsAlive) ;
System.Threading.Thread.Sleep(5000);
// Now I want to somehow call the StopParty() Method
}
}
I don't know if it's really stupid what I'm trying to do but I think its a nice way to stop the "Partythread" in a clean way.
Is this possible or is there a better solution for this?
Thanks for your Ideas.
(I didn't test the Code - just wrote it out of my head)
You call the stop method just the way you called the start method:
party.StopParty();
In order to ensure that the changes made in another thread aren't just cached, the partytime field should be marked as volatile as well.
You should use synchronization facilities, such as CancellationToken.
Your code will look like:
public class PartyClass
{
private readonly CancellationToken _cancellationToken;
public PartyClass(CancellationToken cancellationToken)
{
_cancellationToken = cancellationToken;
}
public void MakeParty()
{
while (!_cancellationToken.IsCancellationRequested)
Console.WriteLine("I'm making a party here");
Console.WriteLine("The party ended. Please leave now");
}
}
public class MainThread
{
public static int Main(String[] args)
{
var cancellationSource = new CancellationTokenSource();
PartyClass party = new PartyClass(cancellationSource.Token);
Thread partyThread = new Thread(party.MakeParty);
partyThread.Start();
System.Threading.Thread.Sleep(5000);
cancellationSource.Cancel();
partyThread.Join();
}
}
It is thread-safe and suitable not only for this, but also for more advanced scenarios, as well as for working with tasks.
If want more threads to ask for the same variable, take care about thread syncrhonization issues (when two threads try to access the same variable).
Im going to show the safest way (might be more than what you need). The best to way to do it is declaring an static object to set a lock in order to make sure you have one thread changing the party flag at once.
public class PartyClass
{
private object _partyTimeLock = new Object(); // executed at class init
private boolean partyTime= true;
public bool IsPartyGoingOn()
{
bool itIsGoingOn = false;
lock(_partyTimeLock) {
itIsGoingOn = partyTime;
}
return itIsGoingOn;
}
public void StopParty()
{
lock(_partyTimeLock) {
partyTime = false;
}
}
public void MakeParty()
{
while(IsPartyGoingOn()) {
Console.WriteLine("I'm making a party here");
}
Console.WriteLine("The party ended. Please leave now");
}
}
In this example here, no matter who try to call the IsPartyGoingOn(), you will never have an issue (no matter if it the class own thread or another one). The lock keyword will guarantee you are doing the right way.

Do I need to use locks when simply assigning variables?

When multithreading I know that I need to lock variables if doing things like adding and item to a list etc or I would get a cross thread exception. But do I need to lock them when just assigning variables? I don't mind about if a thread getting an old instance of the variable - I just don't want it to error. Here is an example of what I mean:
public void Run()
{
var thread1 = new Thread(new ThreadStart(Test));
var thread2 = new Thread(new ThreadStart(Test));
thread1.Start();
thread2.Start();
}
private static int _test;
private void Test()
{
while (true)
{
_test += 1;
}
}
If you're just assigning an int, then no. But here you're not just assigning. You're incrementing. So you need some kind of synchronization.
In you want to increment, use Interlocked.Increment:
Interlocked.Increment(ref _test);
Running the code should give you your answer... instead of while(true) write for(i=1;1<1e6;i++) , write the result to screen and run it.
You'll see it does not add up to 2e6, but rather something around 1.2e6. So yes, you need to lock if you want to get out 2e6.
Don't just hypothesize, after that always test and assert.
You have to remember the thread could also be looking at a stale copy, by locking you assure that the version of the variable you are looking at is being refreshed
When I first started coding and thought that maybe I don't need the freshest copy of the variable I would get stuck in infinite loops because I assume the variable would be updated eventually, but if the variable was cached then it would never update
I included examples with brief descriptions, don't worry about the way the thread is started, that is not relevant
private static bool _continueLoop = true;
private static readonly object _continueLoopLock = new object();
private static void StopLoop()
{
lock(_continueLoopLock)
_continueLoop = false;
}
private static void ThreadALoopWillGetStales()
{
while(_continueLoop)
{
//do stuff
//this is not guaranteed to end
}
}
private static void ThreadALoopEventuallyCorrect()
{
while(true)
{
bool doContinue;
lock(_continueLoopLock)
doContinue = _continueLoop;
if(!doContinue)
break;
//do stuff
//this will sometimes result in a stale value
//but will eventually be correct
}
}
private static void ThreadALoopAlwaysCorrect()
{
while(true)
{
bool doContinue;
lock(_continueLoopLock)
if(!_continueLoop)
break;
//do stuff
//this will always be correct
}
}
private static void ThreadALoopPossibleDeadlocked()
{
lock(_continueLoopLock)
while(_continueLoop)
{
//if you only modify "_continueLoop"
//after Acquiring "_continueLoopLock"
//this will cause a deadlock
}
}
private static void StartThreadALoop()
{
ThreadPool.QueueUserWorkItem ((o)=>{ThreadALoopWillGetStales();});
}
private static void StartEndTheLoop()
{
ThreadPool.QueueUserWorkItem((o)=>
{
//do stuff
StopLoop();
});
}
public static void Main(string[] args)
{
StartThreadALoop();
StartEndTheLoop();
}
when you start the loop there is a chance that you will continue to get a stale copy of the variable, that is why you do need some sort of synchronization when accessing a across multiple threads

Multiple calls (at once) to a method that can only run one at a time

I have a business logic method that has to be finished before it can be called again. Multiple clients have the ability to call it at once:
public void DoSomething() {}
I was thinking about solving it by making the method private, and creating a new public method to put the requests on a queue:
public void QueueSomeWork()
{
// put on a Queue object
// How will DoSomething get invoked now?
}
private void DoSomething() {}
I'm trying to solve this issue in an elegant way. My issue is how DoSomething() will know to run. I thought about creating a timer to check the queue, but then it would be running 24/7 for something that happens maybe twice per year.
Another thought is to have DoSomething() fire an event when it's done that something else would subscribe to, pick some work off the queue, and call DoSomething(). Is there a better way?
Why don't you use a lock guard?
Eg :
private static Object lockGuard = new Object();
public void DoSomething()
{
lock (lockGuard)
{
//logic gere
}
}
Locking a resource will prevent access from multiple threads in the same time.
More on lock : http://msdn.microsoft.com/en-us/library/c5kehkcz(v=vs.110).aspx
If the numbers are not so high (it depends how DoSomething internals consume resource); I would go with this:
public static async void QueueSomeWork()
{
await Task.Run(() => { DoSomething(); });
}
static readonly object lockObject = new object();
static void DoSomething()
{
lock (lockObject)
{
// implementation
}
}
And if the numbers are higher, you should put a limit on number of allowed queued tasks:
static long numberOfQueuedTasks = 0;
const long MAX_TASKS = 10000; // it depends how DoSomething internals consume resource
public static async void QueueSomeWork()
{
if (numberOfQueuedTasks > MAX_TASKS)
{
var wait = new SpinWait();
while (numberOfQueuedTasks > MAX_TASKS) wait.SpinOnce();
}
await Task.Run(() => { Interlocked.Increment(ref numberOfQueuedTasks); DoSomething(); });
}
static readonly object lockObject = new object();
static void DoSomething()
{
try
{
lock (lockObject)
{
// implementation
}
}
finally
{
Interlocked.Decrement(ref numberOfQueuedTasks);
}
}
Simple way of doing it is by decorating the method with MethodImplOptions.Synchronized, whose function is similar to the synchronized keyword in Java:
[MethodImpl(MethodImplOptions.Synchronized)]
private void DoSomething()
{
// ...
}
The main downside is that this will lock on the current instance, which might lead to deadlock if you're already using locking elsewhere.
Here is an idea. You'd probably want to lock the doSomethingCount when using it, but as for queuing the DoSomething and going on this might work because it runs on a separate thread. Since you were ok with a queue, I assume you want fire and forget and don't actually need to block the caller.
// This will increment the count and kick off the process of going through
// the calls if it isn't already running. When it is done, it nulls out the task again
// to be recreated when something is queued again.
public static void QueueSomething()
{
doSomethingCount++;
if (doSomethingTask == null)
{
doSomethingTask =
Task.Run((Action)(() =>
{
while (doSomethingCount > 0)
{
DoSomething();
doSomethingCount--;
}
}))
.ContinueWith(t => doSomethingTask = null);
}
}
// I just put something in here that would take time and have a measurable result.
private static void DoSomething()
{
Thread.Sleep(50);
thingsDone++;
}
// These two guys are the data members needed.
private static int doSomethingCount = 0;
private static Task doSomethingTask;
// This code is just to prove that it works the way I expected. You can use it too.
public static void Run()
{
for (int i = 0; i < 10; i++)
{
QueueSomething();
}
while (thingsDone < 10)
{
Thread.Sleep(100);
}
thingsDone = 0;
QueueSomething();
while (thingsDone < 1)
{
Thread.Sleep(100);
}
Console.WriteLine("Done");
}
// This data point is just so I could test it. Leaving it in so you can prove it yourself.
private static int thingsDone = 0;
if this is code-only issue, the lock solution is good. But sometimes you run a DB transaction, where series of objects (records) have to be modified with no interference. Good example is when you re-run sequence enumeration of DB records. You can create a lock table in DB and lock a specific defined record in it for update first thing in the transaction. This will prevent other transactions created by your application (in the same code area) to even get to the table you updating. And second call will only proceed after the first one is done. Just a tip.

Should I use ManualResetEvent as a lock object?

The method below should return true for the first call, and false for any other call.
Is there any problem with it? Is it safe to use the reset event for locking?
private ManualResetEvent _resetEvent = new ManualResetEvent(false);
public bool AmIFirst()
{
lock (_resetEvent)
{
bool first = !_resetEvent.WaitOne(0);
if (first)
_resetEvent.Set();
return first;
}
}
Edit: I made some changes after reviewing you're remarks. I was stuck on ManualResetEvent due to former design idea. I actually don't need it at all.
class ActionSynchronizer
{
private Timer _expirationTimer;
private object _locker = new object();
private bool _executionRequired = true;
private SomeDelegate _onExpired = delegate { };
public ActionSynchronizer(SomeDelegate onExpired)
{
_onExpired = onExpired;
expirationTimer = new Timer(OnExpired, null, 30000, Timeout.Infinite);
}
public bool IsExecutionRequired()
{
if (!_executionRequired)
return false;
lock (_locker)
{
if (_executionRequired)
{
_executionRequired = false;
return true;
}
return false;
}
}
private void OnExpired(object state)
{
if (_executionRequired)
{
lock (_locker)
{
if (_executionRequired)
{
_executionRequired = false;
// http://stackoverflow.com/questions/1712741/why-does-asynchronous-delegate-method-require-calling-endinvoke/1712747#1712747
_onExpired.BeginInvoke(_originalAction, EndInvoke, null);
}
}
}
}
}
// ...
{
if (_action.Sync.IsExecutionRequired())
_action.Invoke();
}
I would go a different route here...
private int counter;
...
if(Interlocked.Increment(ref counter) == 1)
{
// yes, I'm first
}
Thread safe, no locks. Or if you are worried about wrapping around Int32:
if(Interlocked.CompareExchange(ref counter, 1, 0) == 0)
{
// yes, I'm first
}
Nowadays, I only ever lock() on a simple System.Object object which I've created just for locking with.
I definitely wouldn't lock() on something like an Event, not because it wouldn't work, but because I think it's potentially rather confusing to be using lock() on an object which it is itself (though completely separately) associated with kernel locking type operations.
I'm not clear what you're actually doing here, but it looks rather like something which a named Mutex might do better.
I think it's better to use lock() for this on an object.
Also, you can prevent excess thread locking by using a "double-checked locking"
e.g.
private object _protection = new object();
private bool _firstTime = true;
public bool AmIFirst()
{
if (!_firstTime)
return false;
lock (_protection)
{
if (!_firstTime)
return false;
_firstTime = false;
return true;
}
}
Note... - there's some interesting comments on double-checked locking - Double-checked locking in .NET - I'm still reading up on this!
Another note... its not clear from the code snippet you posted, but if you are looking to implement a global singleton then solution 4 on http://www.yoda.arachsys.com/csharp/singleton.html is a good place to start
The only thing you need to make sure is that the same object you lock on is accessible to all instances of the code that needs synchronizing. Other than that, no problem.

Categories