java ReentrantLock与synchronized
来源:互联网 发布:前端程序员的技术论坛 编辑:程序博客网 时间:2024/06/05 17:31
synchronized 对象锁
当多个线程在更新共享状态时避免相互冲突,要保证数据的原子性与可见性,我们通常用synchronized上锁,,一个线程访问synchornied代码库或者方法时,其他线程都将暂时不能访问,知道上一个线程调用的这个synchronized执行完成,才能被另外线程调用,synchronized将自动释放锁,此后另外线程等待到这时才能执行
例1:并发线程等待
package com.example;import com.example.bean.User;import java.util.ArrayList;import java.util.Calendar;import java.util.List;import java.util.Random;public class SynchronizedClass { private static List<User> userList = new ArrayList<>(); public static void main(String[] args) throws Exception { new Thread(new Runnable() { @Override public void run() { long startTime= Calendar.getInstance().getTimeInMillis(); System.out.println("------->开始执行:thread:" + Thread.currentThread().getId() + " userSize:" + userList.size() + " execute time:" + Long.toString(startTime)); addUser(); long endTime=Calendar.getInstance().getTimeInMillis(); System.out.println("------->结束执行:thread:" + Thread.currentThread().getId() + " userSize:" + userList.size() + " execute time:" + endTime+" take Time:"+(endTime-startTime)); } }).start(); new Thread(new Runnable() { @Override public void run() { long startTime= Calendar.getInstance().getTimeInMillis(); System.out.println("------->开始执行:thread:" + Thread.currentThread().getId() + " userSize:" + userList.size() + " execute time:" + startTime); addUser(); long endTime=Calendar.getInstance().getTimeInMillis(); System.out.println("------->结束执行:thread:" + Thread.currentThread().getId() + " userSize:" + userList.size() + " execute time:" + endTime+" take Time:"+(endTime-startTime)); } }).start(); } public synchronized static void addUser() { User user = new User("name:" + System.currentTimeMillis(), new Random().nextInt(100)); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } userList.add(user); }}
运行结果:
------->开始执行:thread:13 userSize:0 execute time:1462329339337
------->开始执行:thread:12 userSize:0 execute time:1462329339337
------->结束执行:thread:13 userSize:1 execute time:1462329344348 take Time:5011
------->结束执行:thread:12 userSize:2 execute time:1462329349348 take Time:10011
例二:当一个线程访问对象锁时或者同步方法 其他线程也能访问非同步方法或非同步代码块
package com.example;import com.example.bean.User;import java.util.ArrayList;import java.util.Calendar;import java.util.List;import java.util.Random;public class SynchronizedClass { public static class Test { public void addUser() { synchronized (this) { User user = new User("name:" + System.currentTimeMillis(), new Random().nextInt(100)); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } userList.add(user); } } public synchronized void addUser2() { User user = new User("name:" + System.currentTimeMillis(), new Random().nextInt(100)); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } userList.add(user); } public void sayHello() { System.out.println("------->execute time:" + Calendar.getInstance().getTimeInMillis()); } } private static List<User> userList = new ArrayList<>(); public static void main(String[] args) throws Exception { Test t=new Test(); new Thread(new Runnable() { @Override public void run() { long startTime = Calendar.getInstance().getTimeInMillis(); System.out.println("------->开始执行:thread:" + Thread.currentThread().getId() + " userSize:" + userList.size() + " execute time:" + Long.toString(startTime)); t.addUser(); long endTime = Calendar.getInstance().getTimeInMillis(); System.out.println("------->结束执行:thread:" + Thread.currentThread().getId() + " userSize:" + userList.size() + " execute time:" + endTime + " take Time:" + (endTime - startTime)); } }).start(); new Thread(new Runnable() { @Override public void run() { long startTime = Calendar.getInstance().getTimeInMillis(); System.out.println("------->开始执行:thread:" + Thread.currentThread().getId() + " userSize:" + userList.size() + " execute time:" + startTime); t.addUser(); long endTime = Calendar.getInstance().getTimeInMillis(); System.out.println("------->结束执行:thread:" + Thread.currentThread().getId() + " userSize:" + userList.size() + " execute time:" + endTime + " take Time:" + (endTime - startTime)); } }).start(); new Thread(new Runnable() { @Override public void run() { t.sayHello(); } }).start(); }}
------->开始执行:thread:13 userSize:0 execute time:1462330376305
------->开始执行:thread:12 userSize:0 execute time:1462330376305
------->execute time:1462330376305
------->结束执行:thread:13 userSize:1 execute time:1462330381315 take Time:5010
------->结束执行:thread:12 userSize:2 execute time:1462330386315 take Time:10010
在jdk1.5 之后 java还增加了一种锁机制 Lock
lock的实现类ReentrantLock 比较常用
ReentrantLock 提供多样化的同步,比如时间限制的同步,可以被interrupt的同步(synchronized的同步是不能interrupt的)等。在资源警政不激烈的情况下,性能稍微比synchronized差点点,反之胜之,据官方称(伴随jvm的提升和优化,差距逐步缩小);reentrantLock还能维持常态:
注意lock 必须手动释放,不同于synchronized,通常在finally 代码块中(synchronized 出现异常时jvm会自动释放,而lock jvm不会来管理,所以要确保一定释放)
模板:
Lock lock = new ReentrantLock(); lock.lock(); try { } finally { lock.unlock(); }ReentrantLock 构造方式分为公平锁和非公平锁;synchronized永远是公平的
/** * Creates an instance of {@code ReentrantLock}. * This is equivalent to using {@code ReentrantLock(false)}. */ public ReentrantLock() { sync = new NonfairSync(); } /** * Creates an instance of {@code ReentrantLock} with the * given fairness policy. * * @param fair {@code true} if this lock should use a fair ordering policy */ public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); }公平情况下:操作会排一个队列按顺序执行,来保证执行的顺序性,同时也会消耗更多的时间
不公平情况下,是无序允许插队的,,jvm会自动计算如何处理更快速度来调度插队,理论更快
ReentrantLock获取锁的4种方式:
1:void lock(); 如果获取了锁立即返回,如果别的线程持有锁,当前线程则一直处于休眠状态,直到获取锁;
2:boolean tryLock(); 如果获取了锁立即返回true,如果别的线程持有锁,立即返回false;
3: boolean tryLock(longtime, TimeUnit unit) throwsInterruptedException;如果获取了锁立即返回true,如果别的线程持有锁,会等待参数给定的时间,在等待的过程中,如果获取了锁,立即返回true,如果等待超时,返回false;
4:void lockInterruptibly()throwsInterruptedException;如果获取了锁立即返回,如果没有获取锁,当前线程处于休眠状态,直到当前线程中断
使用场景:防止重复触发:UI疯狂点击,清除无用的临时文件,数据库备份: 建议是用tryLock
同步执行:防止共享资源的冲突,保证同一个时间段内只有一个操作可以使用该资源,如断点续传,使用lock(),当资源被其他线程锁定,会等待锁释放,继续执行
已有任务执行,冗长一段时间后 是否可以继续执行 使用tryLock(time),超过这个时间依旧不可以获得锁立即返回false 使用注意事项,这个方法会抛出中断异常
synchronized与lock在默认情况下是不会相应中断(interrupt)操作,会继续执行完成,lockInterruptibly提供可中断锁来解决此问题
例3: lock实例
package com.example;import com.example.bean.User;import java.util.ArrayList;import java.util.Calendar;import java.util.List;import java.util.Random;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/** * @author xuanyouwu * @email xuanyouwu@163.com * @time 2016-05-04 11:09 */public class LockClass { public static class Test { Lock lock = new ReentrantLock(); public void addUser() { try { lock.lock(); User user = new User("name:" + System.currentTimeMillis(), new Random().nextInt(100)); try { Thread.sleep(5000); } catch (InterruptedException e) { } userList.add(user); } finally { lock.unlock(); } } } private static List<User> userList = new ArrayList<>(); public static void main(String[] args) throws Exception { Test t=new Test(); new Thread(new Runnable() { @Override public void run() { long startTime = Calendar.getInstance().getTimeInMillis(); System.out.println("------->开始执行:thread:" + Thread.currentThread().getId() + " userSize:" + userList.size() + " execute time:" + Long.toString(startTime)); t.addUser(); long endTime = Calendar.getInstance().getTimeInMillis(); System.out.println("------->结束执行:thread:" + Thread.currentThread().getId() + " userSize:" + userList.size() + " execute time:" + endTime + " take Time:" + (endTime - startTime)); } }).start(); new Thread(new Runnable() { @Override public void run() { long startTime = Calendar.getInstance().getTimeInMillis(); System.out.println("------->开始执行:thread:" + Thread.currentThread().getId() + " userSize:" + userList.size() + " execute time:" + startTime); t.addUser(); long endTime = Calendar.getInstance().getTimeInMillis(); System.out.println("------->结束执行:thread:" + Thread.currentThread().getId() + " userSize:" + userList.size() + " execute time:" + endTime + " take Time:" + (endTime - startTime)); } }).start(); }}
运行结果:
------->开始执行:thread:13 userSize:0 execute time:1462334099726------->开始执行:thread:12 userSize:0 execute time:1462334099726------->结束执行:thread:13 userSize:1 execute time:1462334104736 take Time:5010------->结束执行:thread:12 userSize:2 execute time:1462334109736 take Time:10010
例4:tryLock实例:
package com.example;import com.example.bean.User;import java.util.ArrayList;import java.util.Calendar;import java.util.List;import java.util.Random;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/** * @author xuanyouwu * @email xuanyouwu@163.com * @time 2016-05-04 11:09 */public class LockClass { public static class Test { Lock lock = new ReentrantLock(); public void addUser2() { if (lock.tryLock()) { try { User user = new User("name:" + System.currentTimeMillis(), new Random().nextInt(100)); try { Thread.sleep(5000); } catch (InterruptedException e) { } userList.add(user); } finally { lock.unlock(); } } } } private static List<User> userList = new ArrayList<>(); public static void main(String[] args) throws Exception { Test t = new Test(); new Thread(new Runnable() { @Override public void run() { long startTime = Calendar.getInstance().getTimeInMillis(); System.out.println("------->开始执行:thread:" + Thread.currentThread().getId() + " userSize:" + userList.size() + " execute time:" + Long.toString(startTime)); t.addUser2(); long endTime = Calendar.getInstance().getTimeInMillis(); System.out.println("------->结束执行:thread:" + Thread.currentThread().getId() + " userSize:" + userList.size() + " execute time:" + endTime + " take Time:" + (endTime - startTime)); } }).start(); new Thread(new Runnable() { @Override public void run() { long startTime = Calendar.getInstance().getTimeInMillis(); System.out.println("------->开始执行:thread:" + Thread.currentThread().getId() + " userSize:" + userList.size() + " execute time:" + startTime); t.addUser2(); long endTime = Calendar.getInstance().getTimeInMillis(); System.out.println("------->结束执行:thread:" + Thread.currentThread().getId() + " userSize:" + userList.size() + " execute time:" + endTime + " take Time:" + (endTime - startTime)); } }).start(); }}
运行结果:
------->开始执行:thread:13 userSize:0 execute time:1462334850764
------->开始执行:thread:12 userSize:0 execute time:1462334850764
------->结束执行:thread:12 userSize:0 execute time:1462334850773 take Time:9
------->结束执行:thread:13 userSize:1 execute time:1462334855774 take Time:5010
例5:tryLock(time)实例:
package com.example;import com.example.bean.User;import java.util.ArrayList;import java.util.Calendar;import java.util.List;import java.util.Random;import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/** * @author xuanyouwu * @email xuanyouwu@163.com * @time 2016-05-04 11:09 */public class LockClass { public static class Test { Lock lock = new ReentrantLock(); public void addUser3() { try { if (lock.tryLock(6, TimeUnit.SECONDS)) { try { User user = new User("name:" + System.currentTimeMillis(), new Random().nextInt(100)); try { Thread.sleep(5000); } catch (InterruptedException e) { } userList.add(user); } finally { lock.unlock(); } } } catch (InterruptedException e) { e.printStackTrace(); } } } private static List<User> userList = new ArrayList<>(); public static void main(String[] args) throws Exception { Test t = new Test(); new Thread(new Runnable() { @Override public void run() { long startTime = Calendar.getInstance().getTimeInMillis(); System.out.println("------->开始执行:thread:" + Thread.currentThread().getId() + " userSize:" + userList.size() + " execute time:" + Long.toString(startTime)); t.addUser3(); long endTime = Calendar.getInstance().getTimeInMillis(); System.out.println("------->结束执行:thread:" + Thread.currentThread().getId() + " userSize:" + userList.size() + " execute time:" + endTime + " take Time:" + (endTime - startTime)); } }).start(); new Thread(new Runnable() { @Override public void run() { long startTime = Calendar.getInstance().getTimeInMillis(); System.out.println("------->开始执行:thread:" + Thread.currentThread().getId() + " userSize:" + userList.size() + " execute time:" + startTime); t.addUser3(); long endTime = Calendar.getInstance().getTimeInMillis(); System.out.println("------->结束执行:thread:" + Thread.currentThread().getId() + " userSize:" + userList.size() + " execute time:" + endTime + " take Time:" + (endTime - startTime)); } }).start(); }}
------->开始执行:thread:13 userSize:0 execute time:1462336448589
------->开始执行:thread:12 userSize:0 execute time:1462336448589
------->结束执行:thread:13 userSize:1 execute time:1462336453600 take Time:5011
------->结束执行:thread:12 userSize:2 execute time:1462336458600 take Time:10011
例6:
public void addUser4() { try { lock.lockInterruptibly(); User user = new User("name:" + System.currentTimeMillis(), new Random().nextInt(100)); try { Thread.sleep(5000); } catch (InterruptedException e) { } userList.add(user); } catch (InterruptedException e1) { e1.printStackTrace(); } }
- java ReentrantLock与synchronized
- JAVA 多线程 synchronized与ReentrantLock
- JAVA的ReentrantLock与synchronized 的区别
- ReentrantLock与synchronized比较
- reentrantlock与synchronized
- synchronized与reentrantLock区别
- Synchronized与ReentrantLock
- ReentrantLock与synchronized
- ReentrantLock与synchronized
- reentrantlock与synchronized
- ReentrantLock与Synchronized异同
- ReentrantLock与synchronized
- Synchronized与ReentrantLock区别
- ReentrantLock与synchronized
- java ReentrantLock与synchronized详细分析与例子详解
- Java 中Synchronized 与 ReentrantLock 区别与联系
- ReentrantLock(一):谈谈ReentrantLock与synchronized
- Java中的锁ReentrantLock,condition 与synchronized,volatile
- Android中两种设置全屏的方法!!!
- [Mac] Atom 酷炫插件安装 activate-power-mode
- poj2486 Apple Tree 树上分组背包
- 对象或库文件“*.lib”是使用比创建其他......的解决方法
- How to call stored procedure in Hibernate
- java ReentrantLock与synchronized
- ORACLE死锁
- Java项目中调用Kettle转换
- 浅谈域名发散与域名收敛
- MediaPlayer和SoundPool
- Jindent——让intellij idea 像eclipse一样生成模版化的javadoc注释
- [算法]负载均衡
- 快速理解RxJava源码的设计理念
- 400 (bad request) post