ReentrantLock 和 ReentrantReadWriteLock 类的构造函数都允许传递一个名为 fair 的 boolean 类型的参数,来控制类的行为。
当有一些线程在等待一个锁(ReentrantLock 或 ReentrantReadWriteLock)时,要选择其中一个获得临界区的权限。
上述行为只对 lock() 和 unlock() 方法有意义。因为 tryLock() 方法不会让线程睡眠,所以 fair 属性不影响它的功能。
本节的示例代码在 com.elanzone.books.noteeg.chpt2.sect07 package中
在 第二章第5节的例子 的基础上:
PrintQueue
@@ -6,7 +6,7 @@ import java.util.concurrent.locks.ReentrantLock; public class PrintQueue { - private final Lock queueLock = new ReentrantLock(); + private final Lock queueLock = new ReentrantLock(true);
@@ -20,6 +20,17 @@ public class PrintQueue { } finally { queueLock.unlock(); } + + queueLock.lock(); + try { + Long duration = (long) (Math.random() * 10000); + System.out.println(Thread.currentThread().getName() + ": PrintQueue: Printing a Job during " + (duration / 1000) + " seconds"); + Thread.sleep(duration); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + queueLock.unlock(); + } }
Main
--- a/src/main/java/com/elanzone/books/noteeg/chpt2/sect07/Main.java +++ b/src/main/java/com/elanzone/books/noteeg/chpt2/sect07/Main.java @@ -12,6 +12,11 @@ public class Main { for (int i=0; i<10; i++) { thread[i].start(); + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } } }
所有线程创建的间隔时间是 0.1 秒。第一个请求对锁的控制的线程是线程0,然后是线程1,依此类推。
您可以尝试将传递给锁的构造函数的参数改为 false 切换到 非公平 模式看看区别。
在 非公平 模式下,行为是不保证的,因为锁可以选择任一线程赋予它对受保护代码的权限。 在本例中,JVM不保证线程的执行顺序。