Threading

The next thing I am going to cover is a notably more advanced topic than before in how threading works. For a quick explanation, each program typically is a process, which in turn can consist of one or more threads as necessary. When there is more than one thread, Each thread acts independently of each other with regards to processing. There can be performance benefits when using multiple threads such as when handling I/O based tasks and being able to run threads amongst separate cores. However, there can be issues when variables are used by more than one thread at the same time.

When handling memory, we have to determine what the best course is for handling it. There is the option of having one piece of memory hold all information and have access to it restricted to one thread at a time. There is also having separate parts of memory allocated to each thread and combining the results into one thread. Doing such a thing can result in a slowdown as threads would have to wait one at a time to access a piece of memory. The main factor to keep in mind is that in the second case, when collections of data such as lists or vectors are used, it is necessary to split that information up for each thread to handle and recombine them, which serves to limit the performance increase given when using multiple threads.

With this basic information out of the way, I will show examples of threading at work using various programming languages starting with C++. Before I continue, I will mention that the example I am using is based off of the C++11 standard so the closest equivalent to this before that revision would be via importing the boost libraries. Many libraries (such as the SDL libraries) have their own implementation of threading due to the lack of threading capabilities in the language before this point though so keep that in mind if using an older C++ standard.

//
//  main.cpp
//  threading
//
//  Created by amp on 8/23/13.
//  Copyright (c) 2013 SX. All rights reserved.
//

#include <iostream>
#include <thread>

void loopPrint() {
    for(int i = ; i < 100; i++){
        std::cout << i << "\n";
    }
}

int main(int argc, const char * argv[])
{
    std::thread firstThread(loopPrint);
    std::thread secondThread(loopPrint);
    std::cout << "Threading has begun.\n";
    firstThread.join();
    secondThread.join();
    return ;
}

In the example given, you see the creation of the firstThread and secondThread variables which starts and controls the threads. The join method seen has the program wait for each thread to complete before continuing. In the example above, both threads will output 0 to 99, running at the same time, which is a phenomenon called concurrency. Also, the way that I opted to initialize the threading is a static allocation instead of dynamic as seen in my memory handling tutorials. In short, statically allocated items are put on the stack and removed as soon as they are out of scope. I also wish to point out that abnormalities will most likely be seen when more than one thread is using cout at the same time. The end result is that once both firstThread and secondThread finish up, the program terminates.

The next example I am doing will be in C# with this example:

using System;
using System.Threading;

public class ThreadTesting {
    public static void loopPrint() {
        for(int i = ; i < 100; i++) {
            Console.WriteLine(i);
        }
    }

    public static void Main() {
        Thread firstThread = new Thread(new ThreadStart(loopPrint));
        Thread secondThread = new Thread(new ThreadStart(loopPrint));
        firstThread.Start();
        secondThread.Start();
        Console.WriteLine("Threading has started");
        firstThread.Join();
        secondThread.Join();
    }
}

In the second example given with C#, notice that I tell it manually to start the threads. In addition to this, I use ThreadStart to represent what is to be computed in the thread. The actions taken will essentially be the same in both languages when doing this aside from the slight syntax differences and different processing speeds.

As for Threading in Java, I will admit to not being a fan of how it is implemented as http://docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html states that either an object implementing the runnable interface be passed or the class should inherit from the Thread class, thus becoming a subclass of Thread. I understand Java wanting to be more Object Oriented, but after enough inheritance, there are possibilities of Object Oriented bloat issues. Regardless, it is not too difficult to implement this with our example as instead of doing a loopPrint method/function, we would make a loopPrint class that would implement the runnable interface, create a method called run that would do the loop, and in main we would start the threads with "Thread firstThread = new Thread(new loopPrint());" along with using the start and join methods as seen in the C# example. (I will not show an example of this, instead I recommend doing this independently for the best understanding as from what I have seen creating examples based on guides like these will help re-enforce these examples and provide greater understanding.)

I will note that not all languages support threading. As mentioned before, C++ did not have threading support available via the standard libraries until the C++11 standard. In addition, while Python does have threading capabilities, it is only beneficial to I/O bound tasks as the language uses a global interpreter lock in the CPython implementation (which is considered the de-facto standard for the language) which forces processing to be be handled one part at a time. However, the multiprocessing library allows for true multiprocessing to take place in the language and dodges the limitations given by the global interpreter lock for those using Python 2.6 or newer. For smaller tasks, threading is not really necessary and really should be used when performance is I/O bound or would visibly benefit from multiple threads such as handling large amounts of data.