Race conditions occur when multiple, asynchronously executing threads access the same object (called a shared resource) returning unexpected (wrong) results. Threads often need to share a common resource, for example a file, with one thread reading from the file while another thread writes to the file. They can be avoided by synchronizing the threads which access the shared resource.

An Unsynchronized Example:

class TwoStrings {
 static void print(String str1, String str2) {
 	System.out.print(str1);

	 try {
		 Thread.sleep(500);
	 }
	 catch (InterruptedException ie) {
		}

	 System.out.println(str2);
	}
}

class PrintStringsThread implements Runnable {
 Thread  thread;
 String str1, str2;
 PrintStringsThread(String str1, String str2) {
 	this.str1 = str1;
	this.str2 = str2;
	 thread = new Thread(this);
	 thread.start();
}
	 public void run() {
	 	TwoStrings.print(str1, str2);
	}
}
class TestThread {
public static void main(String args[]) {
	new PrintStringsThread("Hello ", "there.");

	new PrintStringsThread("How are ", "you?");
	new PrintStringsThread("Thank you “, "very much!");
}
}

Sample output:

Hello How are Thank you there.
you?
very much!

When two or more threads try to access the same resource, they need some way to ensure that the resource will be used by only one thread at a time. The process by which this is achieved is called synchronization. Key to synchronization is the concept of a monitor (or semaphore). A monitor is an object that is used as a mutually exclusive lock. All other threads attempting to enter the locked monitor are suspended until the first thread exits the monitor. A thread becomes the owner of the object’s monitor in one of following ways:

  • Option 1: Use synchronized method
  • Option 2: Use synchronized statement on a common object

If a class has at least one synchronized methods, each instance of it has a monitor. A monitor is an object that can block threads and notify them when it is available.

Using Synchronized Methods

You make methods mutually exclusive by declaring them in the class using the keyword synchronized. While a thread is inside the synchronized method, all the other threads trying to call it on the same instance have to wait. Only when the currently executing synchronized method for an object has ended can another synchronized method start for the same object.

A synchronized Method Example:

class TwoStrings {
 synchronized static void print (String str1, String str2) {
 	System.out.print(str1);
	 try {
		 Thread.sleep(500);
	 }
	 catch (InterruptedException ie) {
		}

	 System.out.println(str2);
	}
}
class PrintStringsThread implements Runnable {
 Thread thread;
 String str1, str2;
 PrintStringsThread(String str1, String str2) {
 	this.str1 = str1;
	this.str2 = str2;
	 thread = new Thread(this);
	 thread.start();
}
	 public void run() {
 		TwoStrings.print (str1, str2);
	}
}
class TestThread {
public static void main(String args[]) {
	new PrintStringsThread("Hello ", "there.");

	new PrintStringsThread("How are ", "you?");
	new PrintStringsThread("Thank you “, "very much!");
}
}

Sample Output:

Hello there.
How are you?
Thank you very much!

Synchronized Block Example

class TwoStrings {
 static void print(String str1, String str2) {
 	System.out.print(str1);

	try {
		 Thread.sleep(500);
	 }
	 catch (InterruptedException ie) {
		}

	 System.out.println(str2);
	}
}
class PrintStringsThread implements Runnable {
 Thread thread;
 String str1, str2;
TwoString ts;
	PrintStringsThread(String str1, String str2, TwoString ts) {
 	this.str1 = str1;
	this.str2 = str2;
	this.ts=ts;
	thread = new Thread(this);
	thread.start();
}
	 public void run() {
	 	synchronized (ts){
		ts.print(str1, str2);
		}
}}
class TestThread {
public static void main(String args[]) {

	TwoStrings ts = new TwoStrings();
	new PrintStringsThread("Hello ", "there.“, ts);

	new PrintStringsThread("How are ", "you?“, ts);
	new PrintStringsThread("Thank you “, "very much!“, ts);
}
}

Method

wait() method

wait() method causes a thread to release the lock it is holding on an object; allowing another thread to run.  wait() method is defined in the Object class. wait() can only be invoked from within synchronized code. It should always be wrapped in a try block as it throws IOExceptions. wait() can only be invoked by the thread that owns the lock on the object. When wait() is called, the thread becomes disabled for scheduling and lies dormant until one of four things occur:

  • another thread invokes the notify() method for this object and the scheduler arbitrarily chooses to run the thread
  • another thread invokes the notifyAll() method for this object
  • another thread interrupts this thread
  • the specified wait() time elapses

When one of the above occurs, the thread becomes re-available to the Thread scheduler and competes for a lock on the object.

notify() method

Wakes up a single thread that is waiting on this object’s monitor. If any threads are waiting on this object, one of them is chosen to be awakened. It can only be used within synchronized code. The awakened thread will not be able to proceed until the current thread relinquishes the lock on this object

Producer-Consumer

Imagine a scenario in which there exists two distinct threads both operating on a single shared data area. One thread, the Producer inserts information into the data area whilst the other thread, the Consumer, removes information from that same area. In order for the Producer to insert information into the data area, there must be enough space. The Producer’s sole function is to insert data into the data-area, it is not allowed to remove any data from the area. For the Consumer to be able to remove information from the data area, there must be information there in the first place. The sole function of the Consumer is to remove data from the data area. The solution of the Producer-Consumer problem lies with devising a suitable communication protocol through which the two processes may exchange information.

Producer-Consumer Example(unsynchronized)

public class item {
 	private int contents;
 public int get() {
 	return contents;
}
 public synchronized void put(int value) {
 	contents = value;
 }
}
public class Producer extends Thread {
	private item itm;
 	private int number;
public Producer(item c, int number) {
 	itm = c;
 	this.number = number; }
 public void run() {
	 for (int i = 0; i < 10; i++) {
 		itm.put(i);
 		System.out.println("Producer #" + this.number + " put: " + i);
		 try {
			   sleep((int)(Math.random() * 100));
 		} catch (InterruptedException e) { }
}}}
public class Consumer extends Thread {
	private item itm;
	private int number;
	public Consumer(item c, int number) {
	 itm = c;
	 this.number = number;}
 public void run() {
	 int value = 0;
	 for (int i = 0; i < 10; i++) {
		 value = itm.get();
		 System.out.println("Consumer #" + this.number + " got: " + value);
}}}
public class ProducerConsumerUnsynchronized {
 public static void main(String[] args) {

	item c = new item();
	Producer p1 = new Producer(c, 1);
	Consumer c1 = new Consumer(c, 1);
	 p1.start();
	 c1.start();
}
}

Results:

Results are unpredictable. A number may be read before a number has been produced. Multiple numbers may be produced with only one or two being read.

Result of unsynchronized example

Consumer #1 got: 0
Producer #1 put: 0
Consumer #1 got: 0
Consumer #1 got: 0
Consumer #1 got: 0
Consumer #1 got: 0
Consumer #1 got: 0
Consumer #1 got: 0
Consumer #1 got: 0
Consumer #1 got: 0
Consumer #1 got: 0
Producer #1 put: 1
Producer #1 put: 2
Producer #1 put: 3
Producer #1 put: 4
Producer #1 put: 5
Producer #1 put: 6
Producer #1 put: 7
Producer #1 put: 8
Producer #1 put: 9

Synchronized Producer-Consumer

public class item {
 private int contents;
 private boolean available = false;

public synchronized int get() {
  while (available == false) {
 	 try {
 		 wait();
 	 }
   catch (InterruptedException e) { }
 }
 available = false;
 notifyAll();
 return contents;
}
public synchronized void put(int value) {
 while (available == true) {
    try {
	 wait();
        }
    catch (InterruptedException e) { }
   }
  contents = value;
   available = true;
   notifyAll();
}
}

Result of Synchronized Producer-Consumer:

Producer 1 put: 0
Consumer 1 got: 0
Producer 1 put: 1
Consumer 1 got: 1
Producer 1 put: 2
Consumer 1 got: 2
Producer 1 put: 3
Consumer 1 got: 3
Producer 1 put: 4
Consumer 1 got: 4
Producer 1 put: 5
Consumer 1 got: 5
Producer 1 put: 6
Consumer 1 got: 6
Producer 1 put: 7
Consumer 1 got: 7
Producer 1 put: 8
Consumer 1 got: 8
Producer 1 put: 9
Consumer 1 got: 9

Thread Starvation

If a high priority thread never blocks. Then all other threads will starve. Must be clever about thread priority

yield()

The yield() method gives other threads of the same priority a chance to run. If there are no equal priority threads in the “Runnable” state, then the yield is ignored.

public static void yield();

Thread gives up CPU for other threads ready to run will cause the current thread in the Running state to move to the Runnable state, thus relinquishing the CPU. The thread is then at the mercy of the thread scheduler as to when it will run again.

Example:

class MyThread extends Thread {
	private String name;
	public MyThread(String name) {
		this.name = name;
	}
	public void run() {
		for (int i=0;i<1000;i++) {
			System.out.println(name + ": hello world");
			yield();
		}
	}
}
public class Main3 {
	public static void main(String [] args) {
		MyThread t1 = new MyThread("thread1");
		MyThread t2 = new MyThread("thread2");
		t1.start(); t2.start();
	}
}

Sample Output:

thread1: hello world
thread2: hello world
thread1: hello world
thread2: hello world
thread1: hello world
thread2: hello world
thread1: hello world
thread2: hello world
thread1: hello world
thread2: hello world
thread1: hello world
thread2: hello world
thread1: hello world
thread2: hello world
thread1: hello world
thread2: hello world
thread1: hello world
thread2: hello world
thread1: hello world
thread2: hello world
thread1: hello world
thread2: hello world
thread1: hello world
Tagged with: JAVAJAVA GUIObject OrientedThreads
 

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

 

Looking for something?

Use the form below to search the site:


Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

Related News Feeds

Set your Twitter account name in your settings to use the TwitterBar Section.