修改锁的竞争原则
ReentrantLock和ReentrantReadWriteLock的构造函数都有一个Boolean型参数fairness,默认为false,该参数用来控制改变锁的竞争原则,即两种竞争模式
- non-fair mode:当多个线程等待获取锁时,jvm随机选择其中一个线程获取锁对象,访问临界区;
- fair-mode:在该模式下,jvm会选择等待时间最长的线程来获取锁;
然而tryLock()方法可以不时线程睡眠,所以如果是使用tryLock()那么fairness参数将无效,不会有任何影响;
下面例子中使用一个属性作为实验,看在两种模式下的不同表现;
动手实验
(1)创建PrintQueue
public class PrintQueue { private final Lock queueLock=new ReentrantLock(true); public void printJob(Object document) { queueLock.lock(); try { Long duration=(long)(Math.random()*10000); System.out.printf("%s:PrintQueue: Printing a Job during %d seconds\n", Thread.currentThread().getName(),(duration/1000)); Thread.sleep(duration); } catch (InterruptedException e) { e.printStackTrace(); }finally { queueLock.unlock(); } //------------- queueLock.lock(); try { Long duration=(long)(Math.random()*10000); System.out.printf("%s:PrintQueue: Printing a Job during %d seconds\n", Thread.currentThread().getName(),(duration/1000)); Thread.sleep(duration); } catch (InterruptedException e) { e.printStackTrace(); }finally { queueLock.unlock(); } }}(2)创建Job
public class Job implements Runnable { private PrintQueue printQueue; public Job(PrintQueue printQueue) { this.printQueue = printQueue; } @Override public void run() { System.out.printf("%s: Going to print a document\n", Thread.currentThread().getName()); printQueue.printJob(new Object()); System.out.printf("%s: The document has been printed\n",Thread.currentThread().getName()); } public static void main(String[] args) { PrintQueue printQueue=new PrintQueue(); Thread thread[]=new Thread[10]; for (int i=0; i<10; i++){ thread[i]=new Thread(new Job(printQueue),"Thread "+ i); } for (int i=0; i<10; i++){ thread[i].start(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } }}一次运行结果:
Thread 0: Going to print a document
Thread 0:PrintQueue: Printing a Job during 0 seconds Thread 1: Going to print a document Thread 2: Going to print a document Thread 3: Going to print a document Thread 4: Going to print a document Thread 5: Going to print a document Thread 6: Going to print a document Thread 7: Going to print a document Thread 1:PrintQueue: Printing a Job during 9 seconds Thread 8: Going to print a document Thread 9: Going to print a document Thread 2:PrintQueue: Printing a Job during 8 seconds Thread 3:PrintQueue: Printing a Job during 1 seconds Thread 4:PrintQueue: Printing a Job during 7 seconds Thread 5:PrintQueue: Printing a Job during 4 seconds Thread 6:PrintQueue: Printing a Job during 9 seconds Thread 7:PrintQueue: Printing a Job during 8 seconds Thread 0:PrintQueue: Printing a Job during 0 seconds Thread 8:PrintQueue: Printing a Job during 0 seconds Thread 0: The document has been printed 当fairness设置为true,当printJob()方法执行再次获取Lock时,此时应该是Thread-1等待的时间最长,也是应该最先获取锁的线程,如上输出结果;如果将fairness设置为false,在此观察输出结果,多运行几次发现结果都不一样;要点
了解fairness参数的作用