Showing posts with label Concurrency. Show all posts
Showing posts with label Concurrency. Show all posts

Monday, October 16, 2017

Thread-Safe Generators in Python

In this post, we will go over how to create thread-safe generators in Python. This post is heavily based on this excellent article.

Generator makes life so much easier when coding in Python, but there is a catch; raw generators are not thread-safe. Consider the example below:

We see that the generator does not produce correct output when multiple threads are accessing this at the same time.

One easy way to make it thread-safe is by creating a wrapper class that simply lets only one thread to execute the generator's next method at any given time with threading lock. This is shown below:

Note that the generator now is thread-safe but doesn't execute its next method in parallel. You can also use Python's decorator to make it look even easier, although it basically does the same thing.

Sunday, February 12, 2017

Java Threading: Synchronization II

In the previous post, we looked at how synchronized methods can be used to ensure safe access to a single object, where multiple threads try to read/write to it.

Here, we improve upon the example. In the last post, I mentioned that there were still fixes to be made, and today we will discuss one of them.

Below is the copy from the previous lesson. Take a closer look at the run() method of removeThread, line 54-57 below:


You will notice that the thread continuously checks whether there is at least 1 or more elements in the queue, and when there is, it calls dequeue() method. The question is: can we guarantee that element in the queue will remain in between the two calls? That is, what if another thread calls dequeue() in between, intercepting the element first? This is certainly possible...

Solution? I'd say we fix this issue by having dequeue() method check for the number of elements in the queue. Since dequeue() method is synchronized, it is guaranteed that if there is an element, it will be able to retrieve it for sure. What if there is no element in the queue? It will return immediately with an exception stating that there is no element to retrieve. Thus, we need to modify removeThread run() method to loop dequeue() method continuously until it does not throw an exception. Take a look at code below for implementation.


The modified code above certainly is better than the previous version, but we are not done yet. There are still a few more fixes to be made, and we will tackle one by one in the subsequent posts!

Saturday, February 11, 2017

Android Threading: Handler Example

In this post, we will go over a very simple Handler example for Android development. Hopefully this post will explain and demonstrate why and how to use Handler class in Android.

Consider a very simple app, where you have two buttons: task button and increment button.

Upon click, the task button will notify the user that the task is now running, and carry out some heavy task, which may take up to seconds. When complete, it will notify the user that the task is finally done.

Upon click, the increment button will simply increment counter and display its current value.

Let's take a look at a crude attempt to implement this using a simple Thread. Here is the layout file.

Here is the implementation activity file.


Here, upon the task button click, it launches the task, which is simulated by sleep(3000), on a separate thread so that we don't slow down the main UI thread. However, the problem is that we must wait for this task thread to complete because we need to update the button's text upon completion. Thus, we use join() method to wait for the task to complete. With this implementation, we find that the UI thread becomes unresponsive while waiting. This is NOT a good way of implementing the task.

The core problem is that we ask the task thread to carry out some heavy task, and we need to make sure that the main UI thread does not just sit and wait, but rather do its jobs on its own. The task thread then must communicate with the UI thread and let it know the task is complete, at which point, the UI thread can update the UI accordingly.

The Handler class in Android achieves exactly this, and below is modification that makes use of the Hander class.


As you can see, the task thread will do its job, and when the task is complete, it notifies the main UI thread that the job is done through handler. The handler is created in the main activity, so it is bound to the main UI thread. When the handler receives a message from the task thread that the job is complete, it will then update the button's text. In the meantime, the main UI task carries out its own tasks, such as incrementing the counter when the increment button is pressed.

Of course, one can implement this without using the Handler class, shown below. However, this solution is possible because we are communicating with the UI thread in this example. If, however, you have two different task threads that must communicate with each other, then you need to use the Handler.

Sunday, January 22, 2017

Java Threading: Synchronization I

In this example, we will look into a simple example that uses java's synchronized keyword.
Consider the following unsafe shared queue example first.


public class SharedQueueUnsafe
{
    private int[] queue;
    private int head, tail, num_elems;
    private int size;

    public SharedQueueUnsafe(int size)
    {
        this.size = size;
        queue = new int[size];
        for (int i=0; i<size; i++)
            queue[i] = -1;
        head = tail = num_elems = 0;
    }
    public void enqueue(int data)
    {
        num_elems++;
        System.out.println("inserting " + data + " into the queue");
        try
        {
            Thread.sleep(100);
        }
        catch (InterruptedException ie)
        {
        }
        queue[head] = data;
        head = (head + 1) % size;
    }
    public int dequeue()
    {
        num_elems--;
        int ret = queue[tail];
        tail = (tail + 1) % size;
        return ret;
    }
    public int getElementsInQueue()
    {
        return num_elems;
    }
    static public void main(String[] args)
    {
        SharedQueueUnsafe sharedQueue = new SharedQueueUnsafe(10);
        Thread insertThread = new Thread()
        {
            public void run()
            {
                sharedQueue.enqueue(12345);
            }
        };
        Thread removeThread = new Thread()
        {
            public void run()
            {
                while (sharedQueue.getElementsInQueue() <= 0)
                    ;
                int element = sharedQueue.dequeue();
                System.out.println("retrieved " + element);
            }
        };
        insertThread.start();
        try
        {
            Thread.sleep(50);
        }
        catch (InterruptedException ie)
        {
        }
        removeThread.start();
    }
}

Two threads are created such that one thread is inserting elements while the other is retrieving. To demonstrate racing condition, the enqueue method is designed to be intentionally slow. When I compile and run this, I get

$ javac SharedQueueUnsafe.java && java SharedQueueUnsafe
inserting 12345 into the queue
retrieved -1

This is because the retrieving thread accessed the queue before it was actually inserted, so that it retrieved the initialization value of -1 rather than 12345.

A crude solution to prevent this happening is rather trivial. We simply make sure that enqueue, dequeue, and getElementsInQueue methods to execute exclusively for a single object. That is, however many threads want to access these methods simultaneously, we force only a single thread can actually access only one of the synchronized methods at any given time. This will of course bring up side effect: performance issue, but for not let's not worry about it yet. We just want to solve the racing condition here.

Java language supports keyword synchronized for methods for this purpose. We simply let each method synchronized such that only a single thread can run any one synchronized method at a given time. Other threads must wait until the current thread is done executing the method. This is rather trivial in this case, and the code is as follows:


public class SharedQueueSafe
{
    private int[] queue;
    private int head, tail, num_elems;
    private int size;

    public SharedQueueSafe(int size)
    {
        this.size = size;
        queue = new int[size];
        for (int i=0; i<size; i++)
            queue[i] = -1;
        head = tail = num_elems = 0;
    }
    public synchronized void enqueue(int data)
    {
        num_elems++;
        System.out.println("inserting " + data + " into the queue");
        try
        {
            Thread.sleep(100);
        }
        catch (InterruptedException ie)
        {
        }
        queue[head] = data;
        head = (head + 1) % size;
    }
    public synchronized int dequeue()
    {
        num_elems--;
        int ret = queue[tail];
        tail = (tail + 1) % size;
        return ret;
    }
    public synchronized int getElementsInQueue()
    {
        return num_elems;
    }
    static public void main(String[] args)
    {
        SharedQueueSafe sharedQueue = new SharedQueueSafe(10);
        Thread insertThread = new Thread()
        {
            public void run()
            {
                sharedQueue.enqueue(12345);
            }
        };
        Thread removeThread = new Thread()
        {
            public void run()
            {
                while (sharedQueue.getElementsInQueue() <= 0)
                    ;
                int element = sharedQueue.dequeue();
                System.out.println("retrieved " + element);
            }
        };
        insertThread.start();
        try
        {
            Thread.sleep(50);
        }
        catch (InterruptedException ie)
        {
        }
        removeThread.start();
    }
}

With this new class, we get correct result.

$ javac SharedQueueSafe.java && java SharedQueueSafe
inserting 12345 into the queue
retrieved 12345

Well, the solution above is only a temporary crude solution. There are some more fixes to be made, but let's not worry about them for now. We will revisit this example in subsequent posts (part II).

Saturday, January 21, 2017

Java Threading: Simplest Example

In the series of posts, I will present Java's threading APIs. Today's example is the simplest threading example using anonymous class in Java.

public class SimpleThread
{
    public static void main(String[] args)
    {
        Thread thread1 = new Thread()
        {
            public void run()
            {
                int i = 0;
                while (i < 10)
                {
                    System.out.println(++i);
                    try
                    {
                        sleep(100);
                    }
                    catch (InterruptedException ie)
                    {
                    }
                }
            }
        };
        Thread thread2 = new Thread()
        {
            public void run()
            {
                int i = 0;
                while (i < 10)
                {
                    System.out.println(++i + 10);
                    try
                    {
                        sleep(100);
                    }
                    catch (InterruptedException ie)
                    {
                    }
                }
            }
        };
        thread1.start();
        thread2.start();
    }
}

To compile and run
$ javac SimpleThread.java && java SimpleThread
1
11
2
12
13
3
4
14
5
15
6
16
7
17
8
18
9
19
10
20

This example is easy enough and self-explanatory!