synchronized 对象锁和 ReentrantLock非公平锁tryLock() 的比较
看见 程序里有 Lock,ReentrantLock 表示共享数据块要用 Lock对象锁住了。
一、简单描述
1、synchronized:当没有获得锁时,一直死等,不能放弃
2、ReentrantLock ():无参数的构造器,是默认非公平锁。
非公平锁:随时来,随时取,不管就绪队列是否已经有人了,取不到,就放弃锁。
1>马上试一下,如果不能获得锁就放弃了,逛超市去。
2>可以给一点时间(10分钟内),如果10分钟还没有获得锁,就逛超市去。
二、synchronized,死等,中途不能放弃
1、图形
因为只有一个对象TestSyn,对应一个锁,5个驱动线程都在等,死等,中途不能放弃。
目前大家都在等待锁,就绪队列空了,cpu也空了,
最后:t1[0] 获得锁,t1[3], t1[4], t1[2], t1[1],必须死等,不得中途放弃。
t1[0]释放锁,才能执行锁里面的代码块。
2、代码
package concurrency; public class TestSyn implements Runnable{ private int countobj=0; @Override public void run() { System.out.println(Thread.currentThread().getName()+"开始去取锁!"); synchronized (this) { System.out.println(Thread.currentThread().getName()+"获得锁 countobj!"+(++countobj)); for(int j=0;j<5;j++) System.out.println(Thread.currentThread().getName()+"自增!"+j); } } public static void main(String[] args) throws InterruptedException { TestSyn test =new TestSyn();//一个干活线程 Thread[] t1=new Thread[5]; for (int i=0;i<5;i++) { t1[i]= new Thread(test); //5个驱动线程 t1[i].start(); } System.out.println("结束"); } } |
结果:
Thread-0开始去取锁!
Thread-3开始去取锁!
Thread-4开始去取锁!
Thread-2开始去取锁!
结束
Thread-1开始去取锁!
Thread-0获得锁 countobj!1
Thread-0自增!0
Thread-0自增!1
Thread-0自增!2
Thread-0自增!3
Thread-0自增!4
Thread-1获得锁 countobj!2
Thread-1自增!0
Thread-1自增!1
Thread-1自增!2
Thread-1自增!3
Thread-1自增!4
Thread-4获得锁 countobj!3
Thread-4自增!0
Thread-4自增!1
Thread-4自增!2
Thread-4自增!3
Thread-4自增!4
Thread-2获得锁 countobj!4
Thread-2自增!0
Thread-2自增!1
Thread-2自增!2
Thread-2自增!3
Thread-2自增!4
Thread-3获得锁 countobj!5
Thread-3自增!0
Thread-3自增!1
Thread-3自增!2
Thread-3自增!3
Thread-3自增!4
三、Lock 对象 去锁住 共享数据代码块
步骤: 1、建立固定的Lock 对象 private Lock lock = new ReentrantLock();这语句存放在一个类中对应的对象,
对应 Synchronized (obj)可以是任何对象。
2、要用到共享数据块的前面:lock.lock();
3、释放锁:finally lock.unlock(); 手动释放锁,Synchronized 当代码执行完,自动释放锁。
4 、try{ return 值;}finally{} :return 可有可无,如果想着锁慢点释放,让第二个干活线程也能看见方法返回的数据。
1、图形
这时t1[3],t1[4]同时也来取锁,肯定没有,就放弃了,就绪队列就剩下面三个线程。
剩下t1[0],t1[1],t1[2] 三个线程交叉执行。
2、ReentrantLock():非公平锁
locks.tryLock():立刻取钥匙,不停留
package concurrency; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class TestTryLcok implements Runnable{ private static Lock locks = new ReentrantLock(); private int countobj=0; @Override public void run() { System.out.println(Thread.currentThread().getName()+"开始去取锁!"); boolean captured = false; try { System.out.println(Thread.currentThread().getName()+"取captured前 "+captured); captured=locks.tryLock(); System.out.println(Thread.currentThread().getName()+"取captured后 "+captured); if(captured){ System.out.println(Thread.currentThread().getName()+"获得锁-->"); System.out.println(Thread.currentThread().getName()+"countobj!"+(++countobj)); for(int j=0;j<5;j++) System.out.println(Thread.currentThread().getName()+"自增:"+j); }else{ System.out.println(Thread.currentThread().getName()+" 未获得锁--> "); } }finally { if(captured){ System.out.println(Thread.currentThread().getName()+" 释放锁--> "); locks.unlock(); } } } public static void main(String[] args) throws InterruptedException { TestTryLcok test =new TestTryLcok();//一个对象 Thread[] t1=new Thread[5]; for (int i=0;i<5;i++) { t1[i]= new Thread(test); //5个驱动线程 t1[i].start(); } System.out.println("结束"); } } |
结果:
Thread-0开始去取锁!
Thread-1开始去取锁!
结束
Thread-2开始去取锁!
Thread-2取captured前 false
Thread-1取captured前 false
Thread-2取captured后 true
Thread-3开始去取锁!
Thread-3取captured前 false
Thread-0取captured前 false
Thread-3取captured后 false
Thread-3 未获得锁-->
Thread-4开始去取锁!
Thread-4取captured前 false
Thread-4取captured后 false
Thread-4 未获得锁-->
Thread-2获得锁-->
Thread-1取captured后 false
Thread-2countobj!1
Thread-0取captured后 false
Thread-2自增:0
Thread-1 未获得锁-->
Thread-2自增:1
Thread-0 未获得锁-->
Thread-2自增:2
Thread-2自增:3
Thread-2自增:4
Thread-2 释放锁-->