在多线程操作时。保证一块共享资源的原子性。第一想到的就是用synchronized关键字
在jdk5提供一个更灵活更强大的 ReentrantLock
使用reentrantLock.lock();获得锁 使用reentrantLock.unlock();释放锁
public class ReentrantLockTest { ReentrantLock reentrantLock = new ReentrantLock(); public void add(Object data) throws InterruptedException { try { reentrantLock.lock(); System.out.println("模拟新增耗时"); Thread.sleep(2000); System.out.println("新增完毕"); } finally { // TODO: handle finally clause reentrantLock.unlock(); } } public void get() throws InterruptedException { try { reentrantLock.lock(); System.out.println("模拟获取"); Thread.sleep(1000); System.out.println("新增完毕"); } finally { // TODO: handle finally clause reentrantLock.unlock(); } } public static void main(String[] args) { final ReentrantLockTest reentrantLockTest=new ReentrantLockTest(); new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub try { reentrantLockTest.add(1); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }).start(); new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub try { reentrantLockTest.get(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }).start();; }
synchronized与ReentrantLock区别
1.synchronized是交给jvm来调度的。ReentrantLock是通过java代码控制的
2.在synchronized在很多线程竞争的时候会使性能大大下降ReentrantLock在很多线程竞争是不会
3.ReentrantLock必须配合finally 否则容易产生死锁
ReentrantLock reentrantLock = new ReentrantLock(); public void Test1() { reentrantLock.lock(); /* * 执行逻辑 */ Test2(); } public void Test2() { reentrantLock.unlock(); }
5.ReentrantLock可以进行公平锁选择
什么情况下选用ReentrantLock
1.某个线程在等待一个锁的控制权的这段时间需要中断 tryLock
public class ReentrantLockTest { ReentrantLock reentrantLock = new ReentrantLock(); public void add(Object data) throws InterruptedException { try { reentrantLock.lock(); Thread.sleep(10000); System.out.println("模拟新增耗时"); } finally { // TODO: handle finally clause reentrantLock.unlock(); } } public void get() throws InterruptedException { try { reentrantLock.tryLock(1000, TimeUnit.MILLISECONDS);//尝试获得锁1000毫秒 获取不到放弃 System.out.println("模拟获取"); Thread.sleep(1000); System.out.println("获取完毕"); } finally { // TODO: handle finally clause reentrantLock.unlock(); } } public static void main(String[] args) { final ReentrantLockTest reentrantLockTest=new ReentrantLockTest(); new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub try { reentrantLockTest.add(1); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }).start(); new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub try { reentrantLockTest.get(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("执行其他业务逻辑"); } },"t2").start();; } }
第一个线程获取锁 等待5秒。当reentrantLock.tryLock(1000, TimeUnit.MILLISECONDS) 会尝试获得锁 若果1秒之内没获取 抛出异常 继续往下执行
打印
模拟获取 获取完毕Exception in thread "t2" java.lang.IllegalMonitorStateException at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(Unknown Source) at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(Unknown Source) at java.util.concurrent.locks.ReentrantLock.unlock(Unknown Source) at com.bjsxt.height.concurrent019.ReentrantLockTest.get(ReentrantLockTest.java:32) at com.bjsxt.height.concurrent019.ReentrantLockTest$2.run(ReentrantLockTest.java:56) at java.lang.Thread.run(Unknown Source) 模拟新增耗时
2.需要分开处理一些wait-notify,ReentrantLock里面的Condition应用,能够控制notify哪个线程
public static void main(String[] args) throws InterruptedException { final ReentrantLock reentrantLock = new ReentrantLock(); final Condition condition1= reentrantLock.newCondition(); new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub try { reentrantLock.lock(); condition1.await(); System.out.println("线程1往下执行"); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { reentrantLock.unlock(); } } }).start(); new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub try { reentrantLock.lock(); Thread.sleep(5000); condition1.signal(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { reentrantLock.unlock(); } } },"t2").start(); Thread.sleep(2000); //取消 condition1等待 }
reentrantLock.newCondition()可以new多个 。可以通过reentrantLock.signalAll()唤醒所有等待的condition
3.具有公平锁功能,每个到来的线程都将排队等候
ReentrantLock reentrantLock = new ReentrantLock(true) 则为公平所