Lock与Synchronized小结
来源:互联网 发布:淘宝优惠券卖家发放 编辑:程序博客网 时间:2024/04/28 06:49
【区别】synchronized:对象锁,调用synchronized方法的线程取得该对象锁后,其他线程需要等待该线程释放该对象锁后才能进入该方法。若是持有不同的对象的线程,则可以同时进入该方法。注意:类锁(全局锁)synchronized(A.getClass)与对象锁synchronized(this)的区别【特点】隐式锁,锁的范围是整个方法或代码块中,离开该方法/块后自动释放锁
2.重入锁:ReentrantLock:更灵活的锁机制,提供可轮询和可中断、可定时的锁获取机制。持有该锁的线程可以重复进入该方法(count加1,但只执行一次Method),可以实现更细微的锁颗粒。【特点】需要显式的获取锁和释放锁
使用事例:
class X { private final ReentrantLock lock = new ReentrantLock(); // ... public void m() { lock.lock(); // block until condition holds <span style="font-family: Arial, Helvetica, sans-serif;">一次只能有一个线程进入,锁的颗粒较大</span> try { // ... method body } finally { lock.unlock() } } }
锁的颗粒对并发的控制作用是明显的,例如两个线程对相同的一个属性进行操作,A转账B的两个线程中,一个线程需要等待另一个线程释放该锁才能进入方法,这样是没有问题的。但是两个线程一个是A转账B,一个是C转账D,上面的锁的方法也会等待一个线程执行完毕释放锁后,另一个线程才能获取锁然后执行,这样就比较慢了,线程只能排队执行,不能并发执行。因此需要改进锁实现方法,实现线程合理的并发控制。实现方法(属性上加锁操作,减少锁的颗粒):
import java.util.HashMap;import java.util.Map;import java.util.concurrent.locks.ReentrantLock;/** * @Author : hd * @Date : 2016/8/18 16:27 * @Version : 1.0.0 *//** * 分段锁,系统提供一定数量的原始锁,根据传入对象的哈希值获取对应的锁并加锁 * 注意:要锁的对象的哈希值如果发生改变,有可能导致锁无法成功释放!!! */public class SegmentLock<T> { private Integer segments = 16;//默认分段数量 private final Map<Integer, ReentrantLock> lockMap = new HashMap<>(); public SegmentLock() { init(null, false); } public SegmentLock(Integer counts, boolean fair) { init(counts, fair); } private void init(Integer counts, boolean fair) { if (counts != null) { segments = counts; } for (int i = 0; i < segments; i++) { lockMap.put(i, new ReentrantLock(fair)); } } public void lock(T key) { ReentrantLock lock = lockMap.get(key.hashCode() % segments); lock.lock(); } public void unlock(T key) { ReentrantLock lock = lockMap.get(key.hashCode() % segments); lock.unlock(); }}另一个事例:三个线程同时进入该锁的情况
public class Test { //public static volatile int i=10; static int i=10; @org.junit.Test public void testReenTrant(){ final SegmentLock<String> segmentLock=new SegmentLock<String>(); final String key="2016"; for(int j=0;j<3;j++){ new Thread(new Runnable() { @Override public void run() { try{ segmentLock.lock(key); i=i-1; System.out.println("lock i:"+i); }finally { segmentLock.unlock(key); } System.out.println("unlock i:"+i); } }).start(); } }}/** 结果:lock i:9 unlock i:9 lock i:8 unlock i:8根据结果可知:一个线程获取锁进入方法执行后,释放了该锁,另外两个线程重复获取到了锁
synchronized例子:
class Sync { public synchronized void test() { System.out.println("test开始.."); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("test结束.."); } } class MyThread extends Thread { public void run() { Sync sync = new Sync(); sync.test(); } } public class Main { public static void main(String[] args) { for (int i = 0; i < 3; i++) { Thread thread = new MyThread(); thread.start(); } } } 运行结果://持有不同对象锁 的线程同时进入test开始..test开始..test开始..test结束..test结束..test结束..
class MyThread extends Thread { private Sync sync; public MyThread(Sync sync) { this.sync = sync; } public void run() { sync.test(); } } public class Main { public static void main(String[] args) { Sync sync = new Sync(); for (int i = 0; i < 3; i++) { Thread thread = new MyThread(sync); thread.start(); } } } 运行结果://持有相同对象锁 的线程要等另一个线程的对象锁释放才能进入test开始..test结束..test开始..test结束..test开始..test结束..class Sync { public void test() { synchronized (Sync.class) { System.out.println("test开始.."); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("test结束.."); } } } class MyThread extends Thread { public void run() { Sync sync = new Sync(); sync.test(); } } public class Main { public static void main(String[] args) { for (int i = 0; i < 3; i++) { Thread thread = new MyThread(); thread.start(); } } } 运行结果://对象类锁,无论创建了多少对象都是属于这个类,需要等待这个线程释放锁,其他线程才能进入,全局锁test开始..test结束..test开始..test结束..test开始..test结束..
【总结】开发中,常常需要对锁的粒度对象细化来实现符合逻辑并发控制,ReentrantLock实现了区别于Synchronized的另一种锁的机制,正如api解释的一样
A reentrant mutual exclusion Lock with the same basic behavior and semantics as the implicit monitor lock accessed using synchronized <span style="font-family: Arial, Helvetica, sans-serif;">methods and statements, but with extended capabilities.</span>
和使用synchronized(隐式监视器锁)和语句访问具有相同的基本行为和语义的重入的互斥锁,但功能更强大。
0 0
- Lock与Synchronized小结
- synchronized与lock区别
- Lock 与 Synchronized
- synchronized与lock区别
- Lock与Synchronized区别
- Lock 与Synchronized
- Lock与synchronized
- synchronized 与Lock类
- synchronized与lock
- synchronized 与 Lock 对比
- synchronized 与 lock
- synchronized与Lock
- synchronized与Lock
- synchronized与lock
- Lock接口与synchronized
- synchronized与lock区别
- java lock 与 synchronized
- synchronized 与 Lock
- 开篇2016
- 安卓activity启动模式的应用场景
- 编程语言注释快捷键总结
- 在ubuntu14.04上安装libqglviewer-qt4-dev
- jQuery插件之ajaxFileUpload
- Lock与Synchronized小结
- UVA | Coin Change
- c#扩展方法
- Zookeeper单机模式安装配置
- Android架构系列-封装自己的okhttp
- FRM笔记之金融市场与产品-关于利率
- HttpClient4.5.2调用示例(转载+原创)
- git merge 和 git rebase 小结
- Android 配合Jenkins使用Gradle脚本命令打包上传到蒲公英