Classes and Threads

This is a discussion on Classes and Threads within the Windows Programming forums, part of the Platform Specific Boards category; Hey all, Since I'm not sure whether to put this in the C++ or Windows section I'm just going to ...

  1. #1
    Registered User
    Join Date
    Feb 2004
    Posts
    31

    Classes and Threads

    Hey all,

    Since I'm not sure whether to put this in the C++ or Windows section I'm just going to dump it here.

    I have a question regarding classes and threads. Say you have a class which has two static member functions which serve as the entry points for two different threads:

    Code:
    static DWORD WINAPI Thread1(LPVOID pClassInstance);
    static DWORD WINAPI Thread2(LPVOID pClassInstance);
    Now, let's say these two threads are created and started in another member function of the class (which is not static).
    Each thread receives a pointer to the instance of the class that created them so they can use private resources such as member variables and functions.

    My question then goes as follows:
    Imagine both threads reading data from somewhere. This data is manipulated by the same member function. So, what happens if say Thread1 calls this function, gets suspended by the OS halfway through and Thread2 then calls this same function. I mean, is there a potential danger here that they might share data (like Thread2 overwriting something Thread1 did)?

    I believe local variables exist in each of the threads' own address space, but I just want to be absolutely sure! But what about static local variables? Is it then the same memory both threads access?
    Last edited by Halloko; 10-07-2005 at 06:48 AM.

  2. #2
    Even death may die... Dante Shamest's Avatar
    Join Date
    Apr 2003
    Location
    Malaysia
    Posts
    970
    But what about static local variables? Is it then the same memory both threads access?
    I believe static variables can be accessed by 2 threads.
    Also, if the local variables they're using point to static data, they might modify it too.

  3. #3
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,265
    The local variables are not shared since each thread gets its own stack. Static local variables are not thread safe, and you have to serialize access around them.

  4. #4
    Registered User
    Join Date
    Feb 2004
    Posts
    31
    Thanks guys.

  5. #5
    Disrupting the universe Mad_guy's Avatar
    Join Date
    Jun 2005
    Posts
    258
    Let's say you have this:

    Code:
    long g_Xvariable = 0;
    
    Void Func1() {
     ++g_Xvariable;
    }
    
    Void Func2() {
     ++g_Xvariable;
    }
    Now this code is pretty simple. If you execute this in a linear fashion it might end up as you want, like this in mnemonics:

    Code:
    mov eax,[g_Xvariable]
    inc eax
    mov [g_Xvariable],eax
    
    ;; Now thread 2 does it's stuff
    
    mov eax,[g_Xvariable]
    inc eax
    mov [g_Xvariable],eax
    This does what it's supposed to, great. But wait, Windows is a pre-emptive multitasking environment. This is what could actually happen:

    Code:
    mov eax,[g_Xvariable]
    inc eax
    mov eax,[g_Xvariable]
    mov [g_Xvariable],eax
    inc eax
    mov [g_Xvariable],eax
    This will come out to g_Xvariable being 1! In fact, you could have five thousand threads do this exact same algorithm but the output could still be 1.

    To synchronize access to things like integers, you should use the windows family of Interlocked functions, thus we can optimize the above two sections of code to this:
    Code:
    long g_Xvariable = 0;
    
    Void Func1() {
     InterlockedIncrement(&g_Xvariable);
    }
    
    Void Func2() {
     InterlockedIncrement(&g_Xvariable);
    }
    The interlocked functions are badass for integer synchronization. However, if you want to synchronize access to certain sections of code and not integers, you can use something called a critical section, and you can use one like this:

    Code:
    int g_Data[20];
    CRITICAL_SECTION gcs_Data;
    
    void Func1() {
     EnterCriticalSection(&gcs_Data);
     for(int i=0;i<20;i++)
      g_Data[i] = i+1;
     LeaveCriticalSection(&gcs_Data);
    }
    
    void Func2() {
     EnterCriticalSection(&gcs_Data);
      for(int i=0;i<20;i++)
       printf("%d ",g_Data[i]);
     LeaveCriticalSection(&gcs_Data);
    }
    That will print out 1-20 appropriately.

    Note that with critical sections, before any thread tries to access the critical section resource it needs to be initialized with a call to InitializeCriticalSection, and when you're done with the section you need to deinitialize it with a call to DeleteCriticalSection
    operating systems: mac os 10.6, debian 5.0, windows 7
    editor: back to emacs because it's more awesomer!!
    version control: git

    website: http://0xff.ath.cx/~as/

  6. #6
    Registered User
    Join Date
    Feb 2004
    Posts
    31
    I usually use mutexes, but it comes out on the same I guess.

  7. #7
    Even death may die... Dante Shamest's Avatar
    Join Date
    Apr 2003
    Location
    Malaysia
    Posts
    970
    According to this article, critical sections are faster than mutexes, but mutexes are cross-process. So if you're not accessing cross-process data, but just static data in your own program, I think critical sections would give better performance.

  8. #8
    Registered User
    Join Date
    Feb 2004
    Posts
    31
    Awesome! I didn't know that.

    Guess I'll be switching to critical sections pretty soon

  9. #9
    Disrupting the universe Mad_guy's Avatar
    Join Date
    Jun 2005
    Posts
    258
    The main difference between Mutexes and Critical Sections and their expenses as synchronization objects is because Mutexes work as Kernel object synchronization techniques. When you have a thread it creates a kernel object, when you have a new process it creates a kernel object, etc. etc.

    By using synchronization techniques such as WaitForSingleEvent you wait for the kernel object passed in the first parameter (I think) to have it's kernel object to set itself so it's no longer signaled. Which is how you can synchronize access so that your thread doesn't continue execution until WaitForSingleObject returns. Mutexes are just the first things you can use with such functions.

    Besides that, if you can avoid global variables in multi-threaded applications, then do so. You can hit deadlocks and pitfalls a lot with global variables and of course you have to deal with synchronization to certain objects and items. Globals are really useful for functions that are entirely time critical.



    Either way, enough of the windows lesson, the point is that if you can get around using a Mutex or a Semaphore with something like a Critical section you should, they're user mode level constructs and provide a slight preformance increase.
    operating systems: mac os 10.6, debian 5.0, windows 7
    editor: back to emacs because it's more awesomer!!
    version control: git

    website: http://0xff.ath.cx/~as/

  10. #10
    Registered User
    Join Date
    Feb 2004
    Posts
    31

    Question

    Quote Originally Posted by bithub
    The local variables are not shared since each thread gets its own stack. Static local variables are not thread safe, and you have to serialize access around them.
    Just to dig further into this. So even though both threads call the same function (that is, they call the same shared member function since they have a pointer to the same class object) the local variables will still be pushed on each thread's own stack?

    What makes it a bit unclear in my head is that both threads are essentially calling the same function in memory.
    Parts of my days are spent bug fixing...err. Iím sorry...Iíve just been reminded that we donít have bugs. We have undocumented features. (Jonathan Ackley on Monkey Island 3)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. How To Initialize concurrent processes in C?
    By Matus in forum C Programming
    Replies: 4
    Last Post: 04-01-2009, 01:59 PM
  2. Ok so I now know how to do...
    By PCG33K in forum C++ Programming
    Replies: 15
    Last Post: 10-04-2007, 09:54 AM
  3. C++: Threads and Classes
    By newntrue in forum C++ Programming
    Replies: 6
    Last Post: 01-13-2007, 04:06 AM
  4. classes are pain
    By pizzapie in forum C++ Programming
    Replies: 5
    Last Post: 09-24-2004, 01:55 PM
  5. help with classes or threads or something :)
    By btq in forum C++ Programming
    Replies: 1
    Last Post: 06-18-2002, 12:13 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21