Go: "Java concurrency Programming" 12: Early Notification issues notifyall in inter-thread communication (with code)

Source: Internet
Author: User

Reprint Please specify source:http://blog.csdn.net/ns_code/article/details/17229601

If a thread waits for a notification, but the thread waits for a condition that is not satisfied, the thread is given an early notification, and if the condition is satisfied for a short period of time, but changes again quickly and becomes no longer satisfied, an early notification will also occur. This behavior sounds strange, and the following is an example program to illustrate the problem.

Quite simply, two threads wait for the element in the list to be deleted while the other line is impersonating to add items to it. The code is as follows:

[Java]View PlainCopy
  1. Import java.util.*;
  2. Public class Earlynotify extends Object {
  3. private list List;
  4. Public earlynotify () {
  5. List = Collections.synchronizedlist (new LinkedList ());
  6. }
  7. Public String RemoveItem () throws interruptedexception {
  8. Print ("in RemoveItem ()-entering");
  9. synchronized (list) {
  10. if (List.isEmpty ()) { //Here is a danger with an if statement
  11. Print ("in RemoveItem ()-About to wait ()");
  12. List.wait ();
  13. Print ("in RemoveItem ()-Do with Wait ()");
  14. }
  15. //Delete element
  16. String item = (string) list.remove (0);
  17. Print ("in RemoveItem ()-leaving");
  18. return item;
  19. }
  20. }
  21. public void AddItem (String item) {
  22. Print ("in AddItem ()-entering");
  23. synchronized (list) {
  24. //Add element
  25. List.add (item);
  26. Print ("in AddItem ()-just added: '" + Item + "'");
  27. //Add, notify all threads
  28. List.notifyall ();
  29. Print ("in AddItem ()-Just notified");
  30. }
  31. Print ("in AddItem ()-leaving");
  32. }
  33. private static void print (String msg) {
  34. String name = Thread.CurrentThread (). GetName ();
  35. SYSTEM.OUT.PRINTLN (name + ":" + msg);
  36. }
  37. public static void Main (string[] args) {
  38. final earlynotify en = new earlynotify ();
  39. Runnable RunA = new Runnable () {
  40. public Void Run () {
  41. try {
  42. String item = En.removeitem ();
  43. Print ("in Run ()-returned: '" +
  44. Item + "'");
  45. } catch (Interruptedexception ix) {
  46. Print ("interrupted!");
  47. } catch (Exception x) {
  48. Print ("threw an Exception!!!  \ n "+ x);
  49. }
  50. }
  51. };
  52. Runnable Runb = new Runnable () {
  53. public Void Run () {
  54. En.additem ("hello!");
  55. }
  56. };
  57. try {
  58. //Start the first thread to delete an element
  59. Thread threadA1 = new Thread (RunA, "threadA1");
  60. Threada1.start ();
  61. Thread.Sleep (500);
  62. //Start the second thread to delete an element
  63. Thread threadA2 = new Thread (RunA, "threadA2");
  64. Threada2.start ();
  65. Thread.Sleep (500);
  66. //Start thread that adds elements
  67. Thread threadb = new Thread (Runb, "threadb");
  68. Threadb.start ();
  69. Thread.Sleep (10000); //wait ten seconds
  70. Threada1.interrupt ();
  71. Threada2.interrupt ();
  72. } catch (Interruptedexception x) {}
  73. }
  74. }

The results of the implementation are as follows:

Analysis: First start threada1,threada1 call Wait () in RemoveItem () to release the object lock on the list. After 500ms, start threada2,threada2 call RemoveItem (), get the object lock on the list, and find that the list is empty, blocking at the wait () method, freeing the object lock on the list. After 500ms, start threadb, call AddItem, get the object lock on the list, add an element to the list, and notify all threads with Notifyall.

ThreadA1 and ThreadA2 both return from Wait (), wait for an object lock on the list object, and attempt to remove the added element from the listing, which can cause trouble and only one of the operations succeeds. Assuming that threadA1 acquires the object lock on the list and deletes the element successfully, when exiting the synchronized block, it frees the object lock on the list, and ThreadA2 acquires the object lock on the list, and continues to delete the elements in the list. But the list is empty, which throws indexoutofboundsexception.

To avoid this, simply change the IF statement of the wait perimeter to a while loop, so that when the list is empty, the thread will continue to wait instead of executing the code to delete the elements in the list.

The result of the modified execution is as follows:

Summary: When using the thread's wait/notification mechanism, it is generally necessary to call the wait () method in the while loop, so that the while loop exits when the condition is met, which generally also uses a Boolean variable (or any other condition that can determine the true or false). As in this article, List.isEmpty ()), when the condition of the while loop is met, enters the while loop, executes the wait () method, does not satisfy the condition of the while loop, and executes the subsequent code.

Go: "Java concurrency Programming" 12: Early Notification issues notifyall in inter-thread communication (with code)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.