Thread in JAVA : Part-2

In previous part, we had seen about thread control. thread creation methods and thread priority information. Today we will look on next part in java threading.

Using the synchronized Keyword:

  • In this, it describes the use of the synchronized keyword. It provides the JAVA programming language with a mechanism that enables a programmer to control threads that are sharing data.

The Problem:

Imagine a class that represents a stack. This class may appear first as:

  1. public class MyStack
  2. {
  3. int idx = 0;
  4. char [] data = new chat[6];
  5. public void push()
  6. {
  7. data [idx] = c;
  8. idx++;
  9. }
  10. public chat pop()
  11. {
  12. idx–;
  13. return data[idx];
  14. }
  15. }

 

  • The class makes no effort to handle the overflow or underflow of the stack, and the stack capacity is limited. However, these aspects are not relevant to this discussion.
  • The behavior of this model requires that the index value contains the arrays subscript of the next empty cell in the stack.
  • The pre-decrement, post-decrement approach generates this information.
  • Imagine now two threads have a reference to a single instance of this class. One thread is pushing data onto the stack and other, more or less independently, is popping data off of the stack.
  • In the principle, the data is added and removed successfully. However, there is a potential problem.
  • Suppose thread a is adding characters and thread b is removing characters. Thread a has just deposited a character, but has not yet incremented the index counter.
  • For some reason, this thread is now preempted. At this point, the data model represented in the object is inconsistent.

buffer |p|q|r| | | |

Idx = 2

  • Specifically, consistency requires either idx = 3 or that the characters has not yet been added.
  • If thread a resumes execution, there may be no damage, but suppose thread b was waiting to remove a character.
  • While thread a is waiting for another chance to run, thread b gets its chance to remove a character.
  • There is an inconsistent data situation on entry to the pop method, yet the pop method proceeds to decrements the index value.

buffer |p|q|r| | | |

Idx = 1

  • This effectively serves to ignore the character r. After this, it then returns the character q. So far, the behavior has been as if the letter r had not been pushed, so it is difficult to say that there is a problem.
  • But look at what happens when the original thread, a, continues to run.
  • Thread a picks up where it left off, in the push method, and it proceeds to increment the index value. Now you have the following:

buffer |p|q|r| | | |

Idx = 2

  • This configuration implies the q is valid and the cell containing r is the next empty cell. In other words, q is read as having been placed into the stack twice, and the letter ‘r’ never appears.
  • This is  a simple example of general problem that arises when multiple threads are accessing shared data.
  • You need a mechanism to ensure that shared data is in a consistent state before any thread starts to use it for a particular task.
  • One approach would be to prevent thread a from being switched out until it completes the critical section of the code.
  • This approach is common in low-level machine programming but is generally inappropriate in multi-user systems.
  • Another approach, and the one on which JAVA technology worked, is to provide a mechanism to treat the data delicately. This approach provides a thread atomic with access to data regardless of whether that thread gets switched out in the middle pf performing that access.

 

Threads in Java Part 2

 

The Object Lock Flag:

  • In JAVA technology, every object ha sa flag associated with it. You can think of this flag a lock flag.
  • The keyword synchronized enables interaction with this flag, and provides exclusive access to code that affects shared data.the following is the modified code fragments:
  1. public class MyStack
  2. {
  3. public void push()
  4. {
  5. synchronized(this)
  6. {
  7. data [idx] = c;
  8. idx++;
  9. }
  10. }
  11. }
  • When the thread reaches the synchronized statement, it examines the object passed as the arguments, and tries to obtain the lock flag from that object before continuing.
  • You should realize that this does not protect the data. If the pop method of the shared data object is not protected by synchronized, and pop is invoked by another thread, there is still a risk of damaging the consistency of the data.
  • All methods accessing shared data must synchronize on the same lock if the lock is to be effective.
  1. public char pop()
  2. {
  3. synchronized(this)
  4. {
  5. idx–;
  6. return data[idx];
  7. }
  8. }
  • Above code illustrates what happens if pop is protected by synchronized and another thread tries to execute an object’s pop method while the original thread holds the synchronized object’s lock flag.
  • When the thread tries to execute the synchronized(this) statement, it tries to take the lock flag from the object this.
  • Because the flag is not present, the thread cannot continue execution. The thread then joins a  pool of waiting threads that are associated with that object’s lock flag.
  • When the flag is returned to the object, a thread that was waiting for the flag is given it, and the thread continues to run.

Releasing the Lock Flag:

  • A thread waiting for the lock flag of an object cannot resume running until the flag is available. Therefore, it is important for the holding thread to return the flag when it is no longer needed.
  • The lock flag is given back to its object automatically. When the thread that holds the lock passes the end of the synchronized code block for which the lock was obtained, the lock is released.
  • JAVA technology ensures that the lock is always returned automatically, even if an encountered exception, break statement, or a return statement transfers code execution out of a synchronized block.
  • Also, if a thread executes nested blocks of code that are synchronized on the same object, that object’s flag is released correctly on exit from the outermost block and the innermost block is ignored.
  • These rules make using synchronized blocks much simpler to manage than equivalent facilities in some other systems.

Sourabh Bhunje

Sourabh Bhunje, B.E. IT from Pune University. Currently Working at Techliebe. Professional Skills: Programming - Software & Mobile, Web & Graphic Design, Localization, Content Writing, Sub-Titling etc. http://techliebe.com/about-us

Leave a Reply