Archive for September, 2008

ผมรู้แล้วว่าทำไมผู้ชายถึงเลว

admin September 15th, 2008

คุณคงจะได้ยินผู้หญิงพูดว่า “ผู้ชายมันก็เลวกันทั้งโลก” แนวความคิดนี้เป็นทียอมรับกันแพร่หลายมากในปัจจุบัน การสำรวจเบื้องต้นพบว่า กลุ่มผู้หญิงที่ผ่านการอกหักมาแล้ว ไม่ต่ำกว่าสามครั้งจะมีแนวโน้มคล้อยตามแนวความคิดนี้ มากเป็นพิเศษ จนถึงทุกวันนี้ก็ยังไม่มีสถาบันวิจัยใด ทำการค้นคว้าทดลองอย่างจริงจัง พอที่จะสรุปได้ว่าสมมุติฐานนี้เป็นจริงหรือไม่ เข้าใจว่าเป็นเพราะการสุ่มตัวอย่างผู้ชายทั้งโลกนั้น ต้องใช้งบประมาณมหาศาล อีกทั้งในปัจจุบัน กระบวนการตรวจสอบ ว่ากลุ่มตัวอย่างเป็น “ชายแท้” หรือไม่นั้นก็ยังมีค่าความคลาดเคลื่อนมากเหลือเกิน หากว่าแนวสมมุติฐานนี้เป็นจริง ผมขอเสนอหนึ่งทฤษฎีที่อาจจะสามารถนำมาอธิบายได้ว่า ทำไมผู้ชายสมัยนี้ถึงเลว

ย้อนกลับไปในสมัยที่ผู้ชายดีๆ ยังมีอยู่มากบนพื้นโลก ผู้ชายเหล่านี้ล้วนแต่เป็นสุภาพบุรุษ ผู้ดำรงตนอยู่ในคลองธรรมอันควร และไม่เคยได้นำตัวเองไปสุ่มเสี่ยง ต่อสิ่งอบายทั้งหลายแต่อย่างใด แต่ทั้งๆที่ประกอบไปด้วยคุณสมบัติที่ดีเหล่านั้น ผู้ชายเหล่านี้กลับไม่ได้รับความสนใจ จากผู้หญิงเท่าที่ควร ที่รักดีนั้นถูกมองเป็นน่าเบื่อ ที่มั่นคงนั้นถูกเห็นเป็นจืดชืด ผู้หญิงกลับลุ่มหลงในคุณสมบัติด้านตรงข้าม กับที่พวกเขามีโดยสิ้นเชิง จนถึงขนาดมีคำกล่าวว่า “ผู้หญิงมักชอบผู้ชายเลว” เหตุการณ์เป็นเช่นนี้มานับร้อยๆปี จากทฤษฎีการอยู่รอดของ Charles Darwin ที่กล่าวไว้ในทฤษฎีการคัดสรรตามธรรมชาติว่า คุณสมบัตที่ดี่ที่เอื้ออำนวยต่อการอยู่รอดนั้น จะถูกถ่ายทอดต่อไปยังลูกหลาน แต่คุณสมบัติที่ไม่เอื้ออำนวย ต่อการดำรงอยู่ของเผ่าพันธุ์นั้นจะลดน้อยลง และหาได้ยากขึ้นเรื่อยๆในรุ่นต่อๆไป ตลอดระยะเวลาร้อยๆปีนี้ พันธุกรรมของผู้ชาย ได้ปรับปรุงเปลี่ยนแปลงมาเรื่อยๆ ยีนส์ที่ส่งผลต่อพฤติกรรมเลวๆ ได้มีจำนวนมากขึ้นเรื่อยๆ เพื่อสงผลต่อความดึงดูดใจจากผู้หญิงนั่นเอง

นักวิทยาศาสตร์บางท่านตั้งข้อสังเกตุว่า อัตราการเพิ่มของยีนส์เลวในผู้ชายนั้น เพิ่มขึ้นทุกปีจนอาจจะอยู่ในระดับ “เลวกว่าหมา” ก็เป็นได้ แม้จะมีผู้หญิงที่ยังมีความสนใจในผู้ชายดีอยู่บ้าง แต่นั้นก็เป็นเพียงผู้หญิงส่วนน้อยในสังคม นักวิทยาศาสตร์ยังได้กล่าวเตือนผู้ชายในปัจจุบัน ที่ยังฝืนทำตัว “รักดี” อยู่ว่า พวกเขาได้ทำตัวฝืนวิถีของธรรมชาติอยู่ ผู้ชายจะเลวนั้นเป็นสิ่งถูกต้องแล้ว การที่ผู้ชายที่เลวกว่าหมา แต่ก็ยังมีผู้หญิงมารักนั้นเป็นข้อพิสูจน์หนึ่ง ว่าการคัดสรรของธรรมชาติใ ห้ผู้ชายเลวนั้นเป็นทิศทางที่ถูกต้องแล้ว

DeadLock

admin September 14th, 2008

Translate from DeadLock and Deadlock Prevention of Jakob Jenkov’s tutorial
Thanks a ton to Jakob for allowing me to translate his excellent tutorial

Deadlock คือการที่เธรด (thread) สองเธรดหรือมากกว่านั้นถูกบล็อคการทำงานไว้เพื่อรอเข้าถือจองล็อค (lock) ที่มีเธรดอื่นใน deadlock นั้นได้ทำการจองไว้เรียบร้อยแล้ว. Deadlock สามารถเกิดขึ้นได้เมื่อเธรดต้องการล็อดเดียวกันพร้อมๆกัน เพียงแต่ได้ทำการขอจองล็อคเหล่านั้นในลำดับที่ต่างกันไป
ตัวอย่างเช่น เธรด1 ทำการจองล็อค A ไว้แล้ว และกำลังพยายามจะขอจองล็อค B แต่ในขณะนั้นเองเธรด2 ที่ได้ทำการจองล็อค B ไว้ได้แล้วก็พยายามจะขอจองล๊อค A ที่เธรด1 ถืออยู่ เธรด1 จะไม่มีวันได้ล๊อค B ไปและเธรด2 ก็ไม่มีวันจะได้ล็อค A ไป นอกจากนั้นแล้วทั้งสองเธรดต่างก็ไม่มีทางจะรู้ได้เลยว่าตัวเองต่างก็ไม่มีวันจะได้ล็อคที่ต้องการมา สถานการณ์เช่นนี้เรียกว่าเกิด deadlock ขึ้น
สถานการณ์นี้อาจจะแสดงให้เห็นได้ดังนี้
Thread 1 locks A, waits for B
Thread 2 locks B, waits for A

ตัวอย่างโค้ดด้านล่างนี้คือคลาส TreeNode ที่ได้ทำการเรียกเมธอดที่ทำการ synchronized ในแต่ละอินสแตนต่างกันไป

public class TreeNode {
  TreeNode parent   = null;
  List     children = new ArrayList();

  public synchronized void addChild(TreeNode child){
    if(!this.children.contains(child)) {
      this.children.add(child);
      child.setParentOnly(this);
    }
  }
  public synchronized void addChildOnly(TreeNode child){
    if(!this.children.contains(child) ) {
      this.children.add(child);
    }
  }
  public synchronized void setParent(TreeNode parent){
    this.parent = parent;
    parent.addChildOnly(this);
  }
  public synchronized void setParentOnly(TreeNode parent){
    this.parent = parent;
  }
}

จากตัวอย่างด้านบน deadlock สามารถเกิดขึ้นได้ ถ้าเธรด(1) ทำการเรียก parent.addChild(child) พร้อมๆกับที่เธรด(2) ทำการเรียก child.setParent(parent) บนอินสแตนของ parent และ child ชุดเดียวกันนี้ ด้านล่างเป็นโค้ดจำลองเพื่อแสดงให้เห็นสถานการณ์นี้

Thread 1: parent.addChild(child); //locks parent
–> child.setParentOnly(parent);

Thread 2: child.setParent(parent); //locks child
–> parent.addChildOnly()

เธรด1 เรียกใช้งาน parent.addChild(child) ซึ่งจากการที่ addChild() นั้นเป็น synchronized ดังนั้นเธรด1 ได้ทำการจองล็อคตัว parent อ็อบเจกต์ไว้ทำให้เธรดอื่นไม่สามารถเข้าใช้งานตัว parent อ็อบเจกต์นี้ได้ (ดูเพิ่มเติมข้อ1) ในขณะเดียวกันนั้นเธรด2 ก็ทำการเรียกใช้ child.setParent(parent) ซึ่ง setParent() ก็เป็น synchronized ดังนั้นเธรด2 ก็ได้ทำการจองล็อคตัว child อ็อบเจกต์ไว้ทำให้เธรดอื่นไม่สามารถเข้าใช้งานตัว child อ็อบเจกต์นี้ได้ (ดูเพิ่มเติมข้อ1) จากนั้นเธรด1 ก็ได้พยายามจะเรียกใช้งาน child.setParentOnly() แต่ก็พบว่า child อ็อบเจกต์ได้ถูกล็อคไปแล้วโดยเธรด2 ดังนั้นเธรด1จะเข้าสู่สถานะบล็อค (เพื่อรอจนกว่าคนที่ล็อค child อ็อบเจกต์ไว้จะปล่อยล็อค เธรด1จึงจะสามารถเข้าทำงานเมธอดนี้ได้) ในลักษณะเดียวกันนั้น เธรด2 ก็ได้พยายามจะเรียก parent.addChildOnly() แล้วก็พบว่า parent อ็อบเจกต์นั้นได้ถูกล็อคไปแล้วโดยเธรด1 เป็นผลให้ เธรด2เข้าสู่สถานะบล็อคเช่นเดียวกัน ถึงตอนนี้ทั้งสองเธรดต่างก็อยู่ในสถานะบล็อคเพื่อรอขอล็อคที่อีกเธรดหนึ่งถืออยู่

สถานการณ์ดังกล่าวข้างบนนั้นจะเกิดขึ้นได้เมื่อเธรดหนึ่งเรียก parent.addChild(child) และ อีกเธรดหนึ่งจะเรียก child.setParent(parent) ในขณะเวลาเดียวกัน บนชุด parent และ child อ็อบเจกต์เดียวกัน โค้ดตัวอย่างนี้อาจจะประมวลผลได้ถูกต้องไปเป็นระยะเวลานานจนกระทั่งเกิด deadlock ขึ้นสักวันนึงในทันทีทันใด

โปรดสังเกตุว่าเพื่อที่ deadlock จะเกิดขึ้นได้นั้นทั้งสองเธรดจะต้องพยายามจะขอจองล็อค “ในขณะเวลาเดียวกัน” จริงๆ ถ้าหากว่าเธรด1 เร็วกว่าเธรด2 สักนิดนึงและได้ทำการจองได้ทั้งล็อค A และ B แล้วละก็ จะทำให้เธรด2 เข้าสู่สถานะบล็อคตั้งแต่ตอนที่พยายามจะขอล็อค B แล้ว ซึ่งก็จะไม่ทำให้เกิด deadlock ขึ้น และเนื่องจากการจัดตารางลำดับเวลาการประมวลผลของเธรดนั้นเป็นสิ่งที่คาดเดาไม่ได้ ดังนั้นเราจึงไม่สามารถทำนายได้ว่า deadlock “จะเกิดขึ้นเมื่อไร” เราบอกได้แต่เพียง “มันสามารถเกิดขึ้นได้”

Deadlock ที่ซับซ้อนขึ้น
Deadlock ยังสามารถเกิดขึ้นได้กับเธรดมากกว่าสองซึ่งทำให้เราตรวจหามันได้ยากขึ้น. ด้านล่างเป็นตัวอย่าง เธรด 4 ตัวเกิด deadlock กัน
Thread 1 locks A, waits for B
Thread 2 locks B, waits for C
Thread 3 locks C, waits for D
Thread 4 locks D, waits for A

การป้องกันไม่ให้เกิด deadlock (Deadlock Prevention)
ในบางสถานการณ์นั้นเราสามารถป้องกัน deadlock ไม่ให้เกิดขึ้นได้ ผมจะอธิบายเทคนิคสามข้อดังต่อไปนี้
1. การจัดลำดับการจองล็อค (Lock Ordering)
2. การจำกัดเวลาในการจองล็อค (Lock Timeout)
3. การตรวจหา deadlock (Deadlock Detection )

1. การจัดลำดับการจองล็อค
Deadlock เกิดขึ้นเมื่อเธรดมากกว่าหนึ่งต้องการจองล็อคตัวเดียวกันแต่ทำการเข้าจองในลำดับที่ต่างกัน ถ้าเราสามารถบังคับให้การจองล็อคทั้งหมดนั้นเป็นไปในลำดับเดียวกันในทุกๆเธรดแล้ว deadlock ก็จะไม่เกิด พิจารณาตัวอย่างต่อไปนี้

Thread 1:

lock A
lock B

Thread 2:

wait for A
lock C (when A locked)

Thread 3:

wait for A
wait for B
wait for C

เมื่อเธรดใดๆ ต้องการล็อคหลายตัวแล้ว เธรดนั้นจะต้องเข้าของล็อคนั้นๆในลำดับที่ถูกกำหนดไว้ก่อนแล้ว เธรดจะต้องไม่จองล็อคสลับลำดับที่ได้กำหนดไว้ ตัวอย่างเช่น ทั้งเธรด 2 และเธรด 3 ต่างก็ไม่สามารถจะเข้าขอจองล็อค C ได้ถ้าไม่ได้ถือครองล็อค A ไว้ได้ก่อนแล้ว และเมื่อเธรด 1 ถือครองล็อค A ไว้อยู่ ดังนั้นเธรด 2 และเธรด 3 ต้องรอให้เธรด 1 ปล่อยการถือครองล็อค A เสียก่อน จากนั้นจึงเข้าถือครองล็อค A ไว้ได้สำเร็จจึงจะสามารถขอเข้าจองล็อค B และ C ต่อไป การจัดลำดับการเข้าจองล็อคนั้นเป็นวิธีที่เรียบง่ายและได้ผลดีในการป้องกันการเกิด deadlock อย่างไรก็ตาม วิธีนี้จะใช้ได้ก็ต่อเมื่อคุณรู้การใช้งานล็อคทั้งหมดล่วงหน้าก่อนการเข้าจองล็อคใดๆ ซึ่งนั่นก็ไม่ใช่สิ่งที่จะสามารถรู้ล่วงหน้าได้ในทุกกรณี

2. การจำกัดเวลาในการจองล็อค
วิธีการป้องกัน deadlock อีกวิธีหนึ่งคือการกำหนดเวลาในการพยายามจองล็อค นั่นคือเธรดจะพยายามขอจองล็อคในระยะเวลาหนึ่งก่อนที่จะเลิกล้มความพยายาม ถ้าเธรดใดไม่สามารถเข้าถือครองล็อคที่ต้องการไว้ได้ทั้งหมดในระยะเวลาที่กำหนด เธรดนั้นจะถอยกลับโดยปล่อยการถือครองล็อคทั้งหมดที่ถือไว้ จากนั้นทำการรอเป็นระยะเวลาหนึ่งก่อนจะพยายามใหม่ ที่ทำการรอเป็นช่วงเวลาหนึ่งนั้นก็เพื่อจะเปิดโอกาสให้เธรดอื่นเข้าขอจองล็อค (ที่เธรดนั้นได้เคยถือครองไว้ก่อนจะถอยกลับ) และทำให้โปรแกรมสามารถทำงานต่อไปได้

ด้านล่างนี้เป็นตัวอย่างของเธรดสองตัวพยายามจะเข้าจองล็อคชุดเดียวกันในลำดับที่ต่างกัน ซึ่งจะเห็นการถอยกลับและพยายามเข้าจองล็อคใหม่อีกครั้งของเธรดทั้งสองตัว

Thread 1 locks A
Thread 2 locks B

Thread 1 attempts to lock B but is blocked
Thread 2 attempts to lock A but is blocked

Thread 1’s lock attempt on B times out
Thread 1 backs up and releases A as well
Thread 1 waits randomly (e.g. 257 millis) before retrying.

Thread 2’s lock attempt on A times out
Thread 2 backs up and releases B as well
Thread 2 waits randomly (e.g. 43 millis) before retrying

ในตัวอย่างนั้นเธรด 2 จะพยายามเข้าจองล็อคใหม่อีกครั้งก่อนเธรด 1 เป็นระยะเวลาประมาณ 200 มิลลิเซค ซึ่งมีความเป็นไปได้สูงที่เธรด 2 จะประสบความสำเร็จในการเข้าจองล็อคทั้งสองตัว จากนั้นเธรด 1 จึงจะพยายามเข้าจองล็อค A ใหม่อีกครั้ง และเมื่อเธรด 2 ทำการประมวลผลเสร็จแล้ว (และทำการปล่อยการถือครองล็อคที่ถืออยู่) เธรด 1 ก็จะมีโอกาสจะเข้าจองล็อคทั้งสองตัวบ้าง (นอกจากว่าเธรด 2 หรือเธรดอื่นๆเข้าทำการจองล็อคชุดนี้แทรกระหว่างนั้น) ข้อควรจำอย่างหนึ่งคือ การที่เธรดไม่สามารถจองล็อคได้สำเร็จ ในระยะเวลาที่กำหนดนั้นไม่ได้หมายความว่าเป็นเพราะมี deadlock เกิดขึ้นเสมอไป อาจจะเป็นได้ว่าเธรดที่ถือครองล็อค (จนทำให้เธรดอื่นหมดเวลาในการพยายามเข้าจองล็อค ) อยู่นั้น ใช้เวลานานในการทำงานจนสำเร็จ นอกจากนั้นแล้ว ถ้ามีเธรดจำนวนมากเข้าแย่งกันขอจองล็อคแล้ว มีโอกาสสูงที่เธรดจะเข้าแย่งกันจองล็อคพร้อมๆกันครั้งแล้วครั้งเล่า แม้ว่าจะเกิดกระบวนการถอยกลับแล้วพยายามใหม่แล้วก็ตาม เหตุการณ์เช่นนี้ อาจจะไม่เกิดกับเธรดแค่สองตัวที่ทำการรอเป็นเวลา 0 ถึง 500 มิลลิเซค ก่อนพยายามใหม่อีกครั้ง แต่ถ้าหากพูดถึงเธรด 10 – 20 ตัวละก็อีกเรื่องหนึ่ง มีโอกาสสูงที่สองเธรดจะรอเป็นเวลาเท่าๆกัน (หรือใกล้เคียงกันพอที่จะทำให้เกิดปัญหา) ก่อนจะเริ่มพยายามจองล็อคใหม่อีกครั้ง ปัญหาอย่างหนึ่งของการกำหนดเวลาในการจองขอจองล็อคก็คือ เราไม่สามารถจะจำกัดเวลาสำหรับ synchronized block (โค้ดส่วนที่ถูกครอบด้วย synchronized keyword) ได้ เราอาจจะต้องสร้างล็อคขึ้นเองหรือไม่ก็ใช้ล็อคของ Java 5 ใน java.util.concurrency

3. การตรวจหา deadlock
การตรวจหา deadlock นั้นจะถูกใช้ในกรณีที่การจัดลำดับการจองล็อคและการกำหนดเวลาในการพยายามจองล็อคนั้นไม่สามารถทำได้ โดยทุกครั้งที่เธรดได้ทำการถือครองล็อคไว้ เธรดนั้นจะถูกบันทึกไว้ในโครงสร้างข้อมูล (map , graph etc.) ของเธรดและล็อค นอกจากนั้นแล้วเมื่อไรก็ตามที่เธรดทำการขอเข้าจองล็อคตัวใด ข้อมูลการร้องงขอนี้ก็จะถูกบันทำไว้ด้วย เมื่อเธรดหนึ่งเธรดใดขอเข้าจองล็อคแล้วถูกปฏิเสธ เธรดนั้นสามารถตรวจสอบกราฟของล็อคเพื่อตรวจหา deadlock ได้ ตัวอย่างเช่น ถ้าเธรด A ขอจองล็อค 7 ที่ถูกถือครองไว้โดยเธรด B แล้ว เธรด A สามารถตรวจสอบได้ว่าเธรด B ได้ทำการขอจองล็อคใดๆที่เธรด A ได้ถือครองอยู่หรือไม่ ถ้าใช่ก็แสดงว่าเกิด deadlock ขึ้น (เธรด A ถือครองล็อค 1 ไว้อยู่และกำลังพยายามขอจองล็อค 7 ขณะเดียวกันเธรด B ได้ทำการถือครองล็อค 7 ไว้และกำลังพยายามจะขอจองล็อค 1) แน่นอนว่ารูปแบบการเกิด deadlock นั้นสามารถมีความซับซ้อน ได้มากกว่าการที่สองเธรดต่างถือครองล็อคที่อีกเธรดหนึ่งต้องการ เธรด Aอาจจะรอเธรด B, เธรด B รอเธรด C, เธรด C รอเธรด D และเธรด D รอเธรด A การที่เธรด A จะสามารถตรวจหา deadlock ได้นั้น เธรด A ต้องตรวจสอบล็อคทั้งหมดที่ที่เธรด B ต้องการทั้งหมดทั้งทางตรงและทางอ้อม จากล็อคที่เธรด B ร้องขอโดยตรงนั้น เธรด A จะต้องมองไปถึงเธรด C (เพราะ เธรด C ถือล็อคตัวหนึ่งที่เธรด B ต้องการอยู่ เธรด A จึงเหมือนกับรอเธรด C ไปด้วย) จากเธรด C มองต่อไปจนถึงเธรด D จึงจะพบว่ามีล็อคตัวหนึ่ง (ที่เธรด B ต้องการทั้งทางตรงและทางอ้อม) ที่ถูกถือครองไว้แล้วโดยเธรด A ถึงตอนนี้จึงสรุปได้ว่าเกิด deadlock ขึ้น ตัวอย่างด้านล่างคือกราฟของล็อคที่ถูกถือครองอยู่ (taken) และกำลังถูกร้องขอการเข้าจอง (requested) ของเธรดสี่ตัว A, B, C และ D โครงสร้างข้อมูลเช่นนี้สามารถนำมาใช้ตรวจหา deadlock ได้

ถามว่าจะทำอย่างไรถ้าเกิด deadlock ขึ้น?
ทางหนึ่งที่เป็นไปได้คือปล่อยการถือครองล็อคทั้งหมด ทำการถอยกลับรอเป็นระยะเวลาหนึ่งแล้วเริ่มพยายามใหม่อีกครั้ง ซึ่งเป็นวิธีเดียวที่ใช้กับการจำกัดเวลาการพยายามจองล็อคต่างกันที่ทำเฉพาะตอนที่เกิด deadlock ขึ้นจริงๆเท่านั้น อย่างไรก็ตาม ถ้าเธรดจำนวนมากทำการเแย่งขอจองล็อคตัวเดียวกันแล้ว ก็มีโอกาสที่เธรดจะเกิด deadlock ซ้ำๆกันบ่อยคร้งแท้ว่าจะทำการถอยกลับและรอพยายามใหม่แล้วก็ตาม

Spurious Wakeup

admin September 14th, 2008

I have finished reading Effective Java long time ago. It is such a great book. The more I passed through each page the more I realized how little I know about java programming. The distance between “coder” and “developer” is really far

I read most of the item listed in the book. One of the items I have skipped was Item 50: Never invoke wait outside a loop. The code below show the concept of this item

synchronized (obj) {
    while (<condition does not hold>)
        obj.wait();

     ... // Perform action appropriate to condition
 }

Looking at the name of the practice, I thought I knew all the reasons behind it so I just skipped it. Today I found an interesting post asking What is spurious wakeup. I read it and found that “threads can wake up on wait() for no reason at all”!!!!! There are quite many good references for this fact and one of them is, guess what, the item 50 of Effective Java. I would have known it for long time ago if I just read it. One of the reasons behind it stated in the item is that

The waiting thread could wake up in the absence of a notify. This is known as a spurious wakeup. Although The Java Language Specification [JLS] does not mention this possibility, many JVM implementations use threading facilities in which spurious wakeups are known to occur, albeit rarely [Posix, 11.4.3.6.1]

I thought sometimes it was OK to call wait() without condition-checking loop if the object to wait on represented just one condition, the object was shared only between waiting and notifying threads and the code’s execution order guaranteed that wait leaks would not occur. Now giving that JVM implementation can send spurious wakeup signal, the condition checking loop is A MUST

Apparently, the spurious wakeup is an issue (I doubt that it is a well known issue) that intermediate to expert developers know it can happen but it just has been clarified in JLS third edition which has been revised as part of JDK 5 development. The javadoc of wait method in JDK 5 has also been updated

A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup. While this will rarely occur in practice, applications must guard against it by testing for the condition that should have caused the thread to be awakened, and continuing to wait if the condition is not satisfied. In other words, waits should always occur in loops

You may wonder (like me) why JLS designer decided to allow this kind of thing to happen. It’s not that I don’t want to use condition checking loop. The checking is the best practice that developers should always do no matter of them knowing anything about the spurious wakeup or not. But I just don’t see the benefit of allowing the wakeup for no reason. It turns out that this is something about performance as stated in Multithread Programming with Java

Due to some arcania in the hardware design of modern SMP machines, it proves to be highly convenient to define them like this. The hardware runs a little faster, and the programmer needs to reevaluate the condition anyway

Next »