Solved

Concurrency issues — Global Variables

Posted on 2011-03-22
9
407 Views
Last Modified: 2012-05-11
Hi

Can some one explain with example and what is the solution to resolve this issue.


Regards
Karan
0
Comment
Question by:KaranGupta
  • 3
  • 3
  • 2
  • +1
9 Comments
 
LVL 4

Expert Comment

by:m_walker
ID: 35196036
Im not a c# coder, so I will leave the example (and points) to someone that is.
Are you talking about a multi treaded application accessing the same variable at the some time?

If so, I expect you will need to use a mutex to gain access to that variable.
As an approach....

wait for mutex "_mutex_var_1"
update variable
release mutex "_mutex_cat_1"

0
 

Expert Comment

by:gkuhrd2001
ID: 35196040
Hi Karan,

Can you please explain what is the problem you are facing with global variables?

Regards
Ankit
0
 

Expert Comment

by:gkuhrd2001
ID: 35196046
Hi,

As I understood by your question you can use
lock
{
}
On these variables when you are accessing them in multithreaded environment.
0
3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

 

Author Comment

by:KaranGupta
ID: 35196253
Hi

I was reading an article why using global variable is a bad practice. This is one reason they stated as "Concurrency issues " in global variables. This is what I want to understand and what is the possible solution for this.


Regards
Karan Gupta
0
 
LVL 4

Expert Comment

by:m_walker
ID: 35197081
Sorry for the long post.  It will be as clear as mud so read and think and re-read.  Then ask questions.
Any code sample is only meant as an example and not actual code.  this post is about concepts.

Hope it helps in some way...

In a single theaded application, then you should not have concurrency issue, but you may use the same variable for two different things and end up with a little mess.

Consider this.
You have a global variable called Total1

Then in one function you set it up such that Total1 = 0
Then every time a "process_data" function gets called it sets Total1 += record_value;
So far so good.  Total1 is a global variable that has a running total of all records processed.
Now you call a sub_total procedure, in which you set Total1 = 0; while (some loop)  Total1+= LoopValue;
At which point Total1 now has a non-intended value.
In the sub_total procedure you call "process_data" and now Total1 is neither the Grand Total nor the SubTotal, a real mess.

As such the subtotal should be a local vairable so it cant be modified outside its function.

In a multi threaded application the mess can get bigger due to the same functions being called by different threads.  if the variables are local, then this will be thread safe, if not then the values will exists in every thread thus be changed by each thread.

If you need to have a global value in a multi threaded application (and there are some good reasons), you need to take care to ensure
1. The value is only used for the intended purpose.  This is done by you program design.
2. The value is not written two by two treads at the same time (this can result if application errors at worse, or invalid data at best).  This can be fixed by locking the variable as shown. by gkuhrd2001.

Think about this for a mulit threaded application.
You have an array for log lines.  You have a next_free pointer to the next free log entry, and a first_log entry to point to the first unprocessed log entry.
TSomeClass *LogLines[1000]; // 1000 Pointers to log data objects
int Next_Free = 0;
int First_Log = 0;

you now have a function called log data that can be called to add lines to the log list

void LogData (AnsiString LogData)
{
  LogLines[Next_Free] = new TSomeClass ();
  LogLines[Next_Free]->Time  = LogData.Time;
 LogLines[Next_Free]->LogData = LogData.LogData;
 Next_Free++;
}

Now two threads call LogData at the same time.
The first thread Creates a new object and stores it in Location 0 (next_free = 0)
The 2nd thread then runs for a while, creates a new (2nd) object and stores its point in location 0;
Then Next_Free++ in thread 2 (Next_Free = 1)
Then Next_Free++ in thread 1 (Next_Free = 2);

So we now have a valid object in location 0.  Its data will be how knows what. then we have an invalid pointer in Location 1 (as no valid object pointer was stored there)

So when the log_to_file function runs it will log some weird data from location 0 and delete that object to free up the memory.  Then application error on the invalid pointer in location 1.....  And the first object created is still taking up memory and you app cant use it.

As such a better code would be...

void LogData (AnsiString LogData)
{
 int LogPos;
   Some code to stop access to NextFree/or wait till NextFree is not locked.
   LogPos = Next_Free;
   Next_Free++;
  release lock on next_free;

  LogLines[LogPos] = new TSomeClass ();
  LogLines[LogPos]->Time  = LogData.Time;
 LogLines[LogPos]->LogData = LogData.LogData;
 
}
0
 

Author Comment

by:KaranGupta
ID: 35197772
Hi m_walker

Thanks for working so hard on this post. I really appreciate that. But I need one favour from you. In the single threaded application you have taken one example in which you are setting the value of Total1 which is a global variable. If possible please give me some more logical example so that I can understand.

In the example given above I am not sure why should we set the value of Total1 in sub_total procedure.

Thanks in advance.

Regards
Karan Gupta
0
 
LVL 4

Accepted Solution

by:
m_walker earned 250 total points
ID: 35197916
My point was just that, there is no need, but bad programming allowed it to be a problem.  When I look at my code I can see habits.
eg:

void SomeFunction1 (void)
{
int loop;
   for (loop = 0; loop < 10; loop++)
     some loop code....
}

void SomeFunction2 (void)
{
int loop;
   for (loop = 0; loop < 10; loop++)
     some loop code....
}

Note how I used the local variable "loop" in both for the loop.  local = no issue.
now consider...

int Counter;
void main (void)
{
  Conter = 0;
}

void Function2 (void)
{
   while (counter < 10)
   {
      some code...
   }
}

void Function1 (void)
{
   while (counter < 10)
   {
      some code
     function2 ();
     counter++;
   }
}

since functino2 is called from functiion1 and counter is global, and function 2 leaves count at 10, then the while loop in function 1 will only run once....

Make counter local in each function and set its initial value to 0 and the problem is fixed.

0
 
LVL 8

Assisted Solution

by:Volox
Volox earned 250 total points
ID: 35203008
The other point that I don't believe m_walker touched upon has to do with initialization....

Let's say you have something like the following:

class MyClass
{
   static List<string> globalList;

   public List<string> GetList()
   {
       if (null == globalList)
       {
          globalList = new List<string>();
          globalList.Add("first value");
       }
       return globalList;
   }
}

In the example below if two threads call GetList at the same time and they both hit the if statement at essentially the same time, they will both create a new list and assign it to the varaible and add a new value to the globalList.  Now if one thread gets through adding it's value before the other does the assignment of the new List, then the list will have one item but will be the list created by the second thread.  If both threads complete the assignment of the new list before either thread adds the first value, then you will end up with two values of "first value" in the list.  The other potential is that one thread creates the list, adds the value, and returns the list all before the assignment happens within the second thread.  In this case the caller to GetList from the first thread now has ahold of a different object entirely than the caller to GetList in the second thread.

For more examples, solutions, etc.  See discussions about threadsafe singletons.  Most common links:
http://www.yoda.arachsys.com/csharp/singleton.html 
http://msdn.microsoft.com/en-us/library/ff650316.aspx
0
 

Author Closing Comment

by:KaranGupta
ID: 35204687
Thanks
0

Featured Post

Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Entity Framework is a powerful tool to help you interact with the DataBase but still doesn't help much when we have a Stored Procedure that returns more than one resultset. The solution takes some of out-of-the-box thinking; read on!
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
This Micro Tutorial demonstrates using Microsoft Excel pivot tables, how to reverse engineer competitors' marketing strategies through backlinks.
This video shows how to quickly and easily add an email signature for all users on Exchange 2016. The resulting signature is applied on a server level by Exchange Online. The email signature template has been downloaded from: www.mail-signatures…

773 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question