I have a method that can be called from many threads, but I just want the 1st thread to do some logic inside the method. So, I'm planning to use a boolean variable. The first thread that comes in, will set the boolean variable to false (to prevent further threads to come inside), and execute the method logic.
Subsequent threads that come to this method, will check the boolean variable. Because it was set to false by the 1st thread, they will skip the method logic.
In code, something like this:
private void myMethod()
{
if (firsTime) //set to true in the constructor
{
firstTime = false; //To prevent other thread to come inside here.
//method logic
}
}
I want to use lock to perform this, but not sure where to put it.
If I lock inside the "if" to change firstTime to false, its possible 2 or more threads already come inside the if (don't want this).
If I lock outside the "if" to change firstTime to false, how can the 1st thread go inside the if to execute the method logic, if firstTime its already set to false??
My question is : how to do the lock to have the desired functionality? (1st thread that comes set the boolean and execute method logic).
I cannot lock over all the method logic, since it will be a very long time consuming operations.
The lock statement acquires the mutual-exclusion lock for a given object, executes a statement block, and then releases the lock. While a lock is held, the thread that holds the lock can again acquire and release the lock. Any other thread is blocked from acquiring the lock and waits until the lock is released.
Locks In Synchronized Methods In this case, the thread acquires the intrinsic lock for the Class object associated with the class. Thus access to class's static fields is controlled by a lock that's distinct from the lock for any instance of the class.
A lock allows you to force multiple threads to access a resource one at a time, rather than all of them trying to access the resource simultaneously. As you note, usually you do want threads to execute simultaneously.
Thread acquires the intrinsic lock when it enters a synchronized method. Thread inside the synchronized method is set as the owner of the lock and is in RUNNABLE state. Any thread that attempts to enter the locked method becomes BLOCKED.
You can use Interlocked.Exchange
to solve this problem. It will set the value of the given variable to the specified value and return the value that used to be in the variable, and it will do it all atomically. Doing this will ensure that only one thread will ever run the code in the if
:
private static int isFirst = 1;
public static void Foo()
{
if (Interlocked.Exchange(ref isFirst, 0) == 1)
{
//DoStuff
}
}
Note that Interlocked.Exchange
has no overload that takes a bool
, which is why you're forced to use an int
(or some other type) instead, using 1
for true and 0
for false.
If you want a solution using lock
, rather than Interlocked
, you can do it through the use of an additional local bool
value:
private static bool isFirst = true;
private static object key = new object();
public static void Foo()
{
bool amFirst;
lock (key)
{
amFirst = isFirst;
isFirst = false;
}
if (amFirst)
{
//DoStuff
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With