?
Solved

Concurrency issues — Global Variables

Posted on 2011-03-22
9
Medium Priority
?
414 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
NEW Veeam Agent for Microsoft Windows

Backup and recover physical and cloud-based servers and workstations, as well as endpoint devices that belong to remote users. Avoid downtime and data loss quickly and easily for Windows-based physical or public cloud-based workloads!

 

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 1000 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 1000 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

NEW Veeam Backup for Microsoft Office 365 1.5

With Office 365, it’s your data and your responsibility to protect it. NEW Veeam Backup for Microsoft Office 365 eliminates the risk of losing access to your Office 365 data.

Question has a verified solution.

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

Today I had a very interesting conundrum that had to get solved quickly. Needless to say, it wasn't resolved quickly because when we needed it we were very rushed, but as soon as the conference call was over and I took a step back I saw the correct …
This article aims to explain the working of CircularLogArchiver. This tool was designed to solve the buildup of log file in cases where systems do not support circular logging or where circular logging is not enabled
Look below the covers at a subform control , and the form that is inside it. Explore properties and see how easy it is to aggregate, get statistics, and synchronize results for your data. A Microsoft Access subform is used to show relevant calcul…
Whether it be Exchange Server Crash Issues, Dirty Shutdown Errors or Failed to mount error, Stellar Phoenix Mailbox Exchange Recovery has always got your back. With the help of its easy to understand user interface and 3 simple steps recovery proced…
Suggested Courses

840 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