Friday, February 29, 2008

The Deadly Question!

One of my favorite questions that I ask during an interview is "What is a deadlock and how do you avoid them?"

Typical answers:

Definition: Deadlock happens when Object 1 is waiting for Object 2 which is waiting for Object 1 again.

Avoiding deadlocks: (Answer 1): Using wait & notify. (Answer 2): Using synchronization.

Not only is the terminology wrong, it also clearly shows that the candidate is not sure with the fundamentals of multi-threading. To be frank, I was asked the same question when I was interviewed and I wasn't able to give a proper answer even though I did good amount of multi-threading before to answer this innocent looking question.

Lets suppose there are two threads T1, and T2 running in your application. T1 is executing a method called method1() and T2 is executing method2(). method1() has acquired lock1 and now it is trying to acquire lock2. But at the same time, method2() has acquired lock2 and it is now trying to acquire lock1. method1() cannot relinquish lock1 until it gets lock2 and finishes the job; method2() cannot relinquish lock2 until it gets lock1 and finishes the job. Both the threads, T1 and T2, are now waiting for one another to proceed their execution which will never happen. This situation is called a deadlock or a deadly embrace.

See the following code that is almost sure to encounter a deadlock during it's execution.
public class DeadLockDemo {
private Object lock1 = new Object();
private Object lock2 = new Object();

public void method1() {
while (true) {
// Acquire lock1 first
synchronized (lock1) {
// Acquire lock2 next
synchronized (lock2) {
System.out.println("Method 1");
}
}
}
}

public void method2() {
while (true) {
// Acquire lock2 first
synchronized (lock2) {
// Acquire lock1 next
synchronized (lock1) {
System.out.println("Method 2");
}
}
}
}

public static void main(String[] args) {
final DeadLockDemo deadLockDemo = new DeadLockDemo();
Thread thread1 = new Thread() {
public void run() {
deadLockDemo.method1();
}
};

Thread thread2 = new Thread() {
public void run() {
deadLockDemo.method2();
}
};

thread1.start();
thread2.start();
}
}

How do we avoid this deadlock here? The typical answers like "synchronizing" the code doesn't solve the problem. Actually, deadlock happens because of improper synchronization. The answer is very simple though. Always acquire the locks in the same order. That is, acquire lock1 and then lock2 or lock2 and then lock1. Yes, it's as simple as that. You can try running the code and check it for yourself.

Till then, happy multi-threading!
Srikanth

Tuesday, February 26, 2008

Cool Firefox Tips

Firefox is my favorite browser despite it's appetite for memory. I use a few command line options and extension that is worth sharing here.



Firefox Profiles: Do you use more than one profile in Firefox? It's a very useful feature. I use it when I would like to log into multiple Gmail accounts at the same time (or you can also use it if you don't use your Gmail account for other Google services such as Reader and Orkut). My main use of the "profiles" feature is during development and testing. You can have one Firefox loaded with all the extensions in the world like Firebug, XPath viewer, various themes, etc. and you can have another light-weight Firefox with a very few extensions which you always need.



So how do you create and use another profile?

$ firefox -profilemanager -no-remote
This opens up the following self explanatory profile launcher window:





As you can see, I have one 'default' and one 'dev' profile. To open a particular profile:

$ firefox -p profile_name -no-remote
The "-no-remote" option is used from Firefox2+ when there's already a profile running.



Firefox Extensions: This is what makes Firefox truly a personal browser. You can create your own extensions or you can download and install the existing ones that are available on the internet. Typically, you browse for an extension and you install it using the "Install" button that is found on the website. But when you do it in this way, the installation only happens for that current profile you are using. To install an extension for all the profiles follow the steps below:



1. Instead of directly clicking on the "Install" button, use right-click button and select "Save Link As..." and save it to your local hard drive. Typically this file is a .xpi or a .jar file.



2. Type the following command on your terminal (or Start -> Run on Windows):

$ firefox -install-global-extension "path_to_saved_extension_file"
# for example:
$ firefox -install-global-extension "c:\downloads\firefox\firebug.xpi"
My favorite Firefox extensions are:

Other recommendations:

Happy browsing!

Srikanth



PS: One more feature you may want to turn on. Firefox on Ubuntu selects the complete URL when you double click on any part of the URL. Try double clicking on any single word on this this URL: http://codeblog.srikanths.net, if you could select the complete URL then you are doing good. Otherwise, follow the steps:

  1. Go to Location bar on Firefox (Alt + D)

  2. Type about:config and press ENTER

  3. In the Filter text box, type this: layout.word_select.stop_at_punctuation

  4. Double click to change the value to FALSE to enable URL selection while double clicking.

I learned this trick from this blog post, so all the credit goes to him/her for this tip.

Tuesday, February 19, 2008

Microformat

As I was browsing through the speculated features of Firefox3, I happened to hit something called Microformats. If you haven't heard about it before, then I must tell you it looks very interesting to me.

Microformats in plain English: The content we read on the Internet using our browser is HTML. Some of those contents belong to a particular category (logically). Examples: Contact details, Events, etc. Take this scenario, lets say that you received an e-mail from your friend and your friend has sent his new address in the content of the e-mail. How nice would it be if you can add that contact details of your friend to your favorite contacts manager applications with just a click of a button without you leaving the browser?

Take another scenario. You are going through Sun's Tech Days website and you see that there is a program next Sunday at your city at 12:00 PM. How nice would it be to add this event to your favorite Calendar application with just a click of a button so that it is added to your schedule and you will be reminded automatically? It would be very nice to do so.

For now, the contact detail or the event detail is lying in the HTML page just like any other text or image and there is no way a software can differentiate them from the normal content. This is where Microformats are going to play a big role. The web site developer while constructing the HTML page will add some meta-data to these content which will tell the browser that the microformatted content belongs to a particular category (say, a contact detail or an event). Then the browser will visually indicate you about the content in someway and provide you an interface to do the action you would like to do (say, add that event to your Calendar). Isn't it cool?

Well, this is what I understood from what I read. It could be completely different.

References:
I like the Microformat's logo, looks green and cute:


PS: I noticed several times Gmail detecting the events in my e-mails' content and presenting an option to add it to Google Calendar. Bravo Gmail! You are ahead of time!

Monday, February 11, 2008

Filter Your 'Tasks View' in Eclipse Using Patterns in TODO

The Feature: Eclipse's Tasks is one of my favorite features in the IDE. You can set reminders right there in your source code and you can see all of them in the Tasks View of the IDE which you can dock it anywhere you want. A sample screenshot of the Tasks View can be seen below.





The Problem: As you can see from the sample screenshot that many people added their own TODOs and FIXMEs. Imagine this for a big project, this will be in hundreds. The point of adding TODOs and FIXMEs right in the source code is that it can be seen more often such that we will be constantly reminded about the unfinished. But when everybody adds, it becomes a problem to keep track of your own Tasks and we may start ignoring them like spam mail. Having control is the key to using this feature, just like e-mail.



The Solution: Fortunately there's a very simple solution to this problem with a little effort. You can create and configure filters, just like you can create filters for your e-mails in Gmail. On the Tasks View you will see the button using which you can create filters. See below:



The rest of the filter configuration work is simple. The Filters dialog pops up and it's very intuitive as what all you can do with it. I typically create filter that contains the string "(srikanths): " in its description. And when I write my TODOs and FIXMEs, I make sure I prefix them with that description. You can come up with your own standard within your team and follow that.



The tasks that I write in the code typically look like this:



// TODO(srikanths): Srikanth should come back to complete this.
// FIXME(srikanths): Srikanth should fix this ASAP or he is dead.






Happy coding!

Srikanth

Thursday, February 7, 2008

Favor 'Read' Time over 'Write' Time

There are thousands of books and millions of web pages that will define modularity and explain you how to achieve them in your program. I am not going to talk about that here. I will answer you why modularity is important.

Any program can be written in just one single method (or function). At least theoretically? The people who are new to programming do this till they are told about "Abstraction", "Encapsulation", etc. Still I see many programmers not following this. They don't modularize their program well. Sure, they understand what is going on but it's not about them. Code should be written keeping in mind that it will be read many times by many people.

557774423456789.

Can you repeat the number? Don't peak! :-)

(Most of us would have not even read it completely just looking at those many digits)

Now, read this: 55-777-44-23456789.

So, which one was easier to read? And which one was easier to write? The first form (without the hyphen separator) was easier to write if you have this number memorized but it is hard to read and recollect for someone who is not familiar with this number. At the same time, the second form took some more time to carefully break at the right places and make it easy for the reader. We invested some more time in writing to save a lot of time for others to memorize this.

This is the whole point. When you write code, you surely understand and it may seem trivial and waste of time to do "separation of concerns." But it's not about you or me, its about that someone who is going to maintain your code in future long after you have moved to another project. Make sure that she won't curse you :-)

Sunday, February 3, 2008

Programming Language of 2007

And the award goes to... Python!?!

Source: http://www.tiobe.com/tpci.htm


I must tell this very frankly, I am pleasantly surprised for one reason: The programming language I learned in 2007 is Python. And now it is declared as the programming language of the year. I am feeling lucky :)

When I started learning it, I hated it for one reason ---Dynamic Typing. Coming from a heavy Java background this was a hard unlearning curve for me. I debated a lot on this topic with my friends and coworkers. I debated on Python forums about this. A very strong debate that I had can be found here (you will have fun reading this, I had fun reading my own post after a very long time!): How to program safely in Python?

Not only this, Guido van Rossum once replied in my post in one of the mailing lists when I asked about Why isn't there a try-catch-finally block in Python? It's available only from Python 2.5+. After pondering, I came to the conclusion that every programming language has its own pros and cons and Python is one such beautiful and stylish language. Yes, you don't have a compiler, yes you will have a python-bite at runtime, but guess what? A compiler only tells that your program is syntactically right. The best way to ensure that your program works is by testing, testing and more testing. Like Bruce Eckel once said, "If it isn't tested, it's broken."