2015年3月10日
1. 概述
java在多线程编程的过程中,为实现线程安全的编程提供了synchronized,关键字,该关键字的作用是为某一代码块加锁,从线程的角度来说,所有需要执行加了syhchronized的代码块的线程,都要排队依次来执行该代码块,从而来确保线程安全。
为什么依次执行代码块就能确保线程安全呢?因为是在代码快里面有些操作的变量,是所有线程都想对其进行修改的,在这个过程中,要确保被修改的变量相对所有线程都是可见的,并且线程在执行代码块的时候,不被打断,也就是“原子性”,才能保证,该变量的值最终是有效的,并且所有线程对其的更改,都能正确的作用到该变量上面。扯的有点远了..
使用synchronized加锁的方式可以有效的解决安全问题,然而,synchronized确带来了很大的性能问题,由于使所有线程都排队等待,如果想得到该锁,必须排队等待,如果有获得该锁的线程一直没有释放锁的话呢,后续的要使用该锁的线程会一直等待下去,这样的解决方式比较古板。
2,synchronized 与lock的使用区别
整是由于synchronized有这样的缺点,所以,jdk1.5以后出现了lock,lock可以实现synchronized的所有功能,但是lock提供了多种灵活处理锁的机制,比如说,如果后续线程想得到该锁,lock制定了几种方案,1,尝试去得到该锁,如果得不到,那我在去做其他的事情,2,尝试得到该锁,如果得不到,我可以等待,但是我不能没有限制的“死等“,要等一段时间之后如果还得不到,我就做其他的事情。等等,lock在synchronized的基础上增加了这些处理方式,使得java在处理锁的过程更加灵活。
synchronized是一个修饰符,而lock是一个接口,所以二者在使用的时候有所不同,lock 里面有一些方法,lock(),tryock(),tryLock(long time,TimeUnit unit),lockInterruptibly() 这些方法是获得锁的,unlock()是用来释放锁的。java里面lock的唯一的实现类是ReentrantLock。
ReentrantLock的使用:
package com.pip.lock;import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class TryLockSO {private int sharedVariable;private Lock lock=new ReentrantLock();public void addValue(){if(lock.tryLock()){try {sharedVariable++;System.out.println("Current Thread:"+Thread.currentThread().getName()+"SharedVariable"+sharedVariable);Thread.sleep(5000);lock.unlock();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}else{try {Thread.sleep(5000);System.out.println("not get lock. Thread:"+Thread.currentThread().getName()+"SharedVariable----"+sharedVariable);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}
3,读写锁(ReadWriteLock)
继续讨论synchronized的缺陷,我们对于变量的操作有时候可以是读操作也可以是写操作,写操作跟写操作发生冲突,读操作跟写操作发生冲突,读跟读操作不发生冲突,synchronized的缺点就是将读操作跟读操作之间也实现互斥 。所以这样就做了一些不必要的互斥。
针对这样的情况,就出现了ReadWriteLock,ReadwriteLock是一个接口,里面有readLock()
,writeLock()
。分别获取读的锁和写的锁,通过这种方式,可以实现读操作的线程之间可以同时进行的,写操作顺序执行,写操作和读的操作都是顺序执行的。
下面试一个测试类,里面有读操作和写操作,并且分别用读的锁和写的锁来加锁。
package com.pip.lock3;import java.util.concurrent.locks.ReentrantReadWriteLock;public class SharedObject {private ReentrantReadWriteLock lock=new ReentrantReadWriteLock();public void read(){lock.readLock().lock();for(int i=0;i<10;i++){System.out.println("CurrentThread :-----"+Thread.currentThread().getName()+" value: "+i);}lock.readLock().unlock();}public void write(){lock.writeLock().lock();for(int i=0;i<10;i++){System.out.println("CurrentThread :-----"+Thread.currentThread().getName()+" value: "+i);} lock.writeLock().unlock();}}
测试类:
package com.pip.lock3;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;import org.junit.Test;public class TestLock {@Testpublic void testReadLock() {final SharedObject so = new SharedObject();Runnable task1 = new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubso.read();}};ExecutorService es = Executors.newCachedThreadPool();es.submit(task1);es.submit(task1);es.shutdown();}@Testpublic void testWriteLock(){final SharedObject so=new SharedObject();Runnable task1=new Runnable(){@Overridepublic void run() {// TODO Auto-generated method stubso.write(); } };ExecutorService es=Executors.newCachedThreadPool();es.submit(task1);es.submit(task1);es.shutdown();}@Testpublic void testReadWrite(){final SharedObject so=new SharedObject();Runnable readTask=new Runnable(){@Overridepublic void run() {// TODO Auto-generated method stubso.read();} };Runnable writeTask=new Runnable(){@Overridepublic void run() {// TODO Auto-generated method stubso.write();} };ExecutorService es=Executors.newCachedThreadPool();es.submit(readTask);es.submit(writeTask);es.shutdown();}}
通过运行结果可以看出:读跟读的操作可以同时进行,写跟写的操作和写跟读的操作是互斥的。
4, 综上所述,sychronized和lock的区别,
(1) synchronized 是修饰符,lock是java里面的接口。
(2)lock可是实现synchoronized的所有功能,并且提供了更加灵活的的处理锁的方式。
(3)synchronized发生异常的时候,可以自动释放锁,而lock必须手动的释放锁,在finally里面。
2015年3月10日相关推荐
- 2015年9月10日
2015年9月10日笔记 Axcur动态设置汇总 图标设置 --点击图标图片向左滑动 步骤:选中该图标(命名为图标1),同时选中"鼠标单击时",→双击用例1→设置面板状态→选中&q ...
- signature=da0cbfb45ebebe4ea0118c0a20df185e,MS15-018:Internet Explorer 累积安全更新:2015 年 3 月 10 日...
此软件更新的英语(美国)版本将安装具有下表所列属性的文件.这些文件的日期和时间按协调世界时 (UTC) 列出.请注意,这些文件在您的本地计算机中的显示日期和时间是您的本地时间加上当前夏令时偏差.如果对 ...
- 【历史上的今天】8 月 10 日:“龙芯”点亮操作系统;谷歌宣布拆分;计算机先驱诞生日
整理 | 王启隆 透过「历史上的今天」,从过去看未来,从现在亦可以改变未来. 今天是 2022 年 8 月 10 日,在 2010 年 5 月,苹果公司市值超过微软,成为全球市值最高的 IT 企业:在 ...
- 始于2015年11月23日,终于2018年08月08日
留念. 2015年11月23日:在一起 2016年01月17日-21日:北京机场,我们❤ 2016年04月16日:去他所在城市--成都 2016年06月04-06日:第一次小旅游--都江堰.青城山 2 ...
- 有杀气童话服务器维护9月,《梦幻西游》手游2015年9月23日维护公告
亲爱的玩家朋友: 为保证服务器的运行稳定和服务质量,<梦幻西游>手游所有服务器将于2015年9月23日8:00停机,进行维护工作.预计维护时间为8:00-9:00.如果在预定时间内无法完成 ...
- 【不容错过】12月10日:纳米孔测序科研团队大会NCM 2020亚太区特别专场
一年一度的纳米孔测序科研团体大会(NCM 2020)主会场已于美国东部时间12月初在线上成功召开,汇集了全球超过50位领先的纳米孔测序学者,分享他们的纳米孔测序最新研究成果. 2020年12月10日, ...
- 微软欢迎所有热爱开源软件的朋友们来投稿![征稿开放时间:2015年8月17日]
Azure是微软的云平台,不仅支持Windows服务器,也深爱着开源世界.通过与开源社区之间的合作, Azure支持了大量的开源软件和框架,涵盖了包括Linux 服务器,Docker, chef, M ...
- linux运维实战练习-2015年9月13日-9月15日课程作业(练习)安排
一.作业(练习)内容: 1.描述shell程序的运行原理(可附带必要的图形说明): 2.总结shell编程中所涉及到的所有知识点(如:变量.语法.命令状态等等等,要带图的哟): 3.总结课程所讲的所有 ...
- WPF学习开发客户端软件-任务助手(下 2015年2月4日代码更新)
时光如梭,距离第一次写的 WPF学习开发客户端软件-任务助手(已上传源码) 已有三个多月,期间我断断续续地对该项目做了优化.完善等等工作,现在重新向大家介绍一下,希望各位可以使用,本软件以实用性为主 ...
最新文章
- 【C++ 语言】命名空间 ( namespace | 命名空间定义 | 命名空间嵌套 | 域作用符 | 与 include 对比 )
- 怎么检测mysql卸载完全_怎么检查mysql有没有删干净
- C++开发中的预处理器
- python中多维数组_python学习笔记-多维数组
- MySQL 性能监控 4 大指标
- Hibernate注解方式实现1-1双向关联
- There is no more space for virtual disk .vmdk.
- 机顶盒系统升级服务器地址,网络机顶盒怎么升级?详细教程分享
- 卷积神经网络专题之上采样与下采样初步理论
- seo网站优化,SEO优化费用
- 2022年最新浙江道路运输安全员真题题库及答案
- nginx中配置location的root(alias)访问同一个地址文件
- 隐藏与显示桌面上的单个图标
- 虚拟化技术发展与虚拟化体系结构
- 概率分布详解 Bernoulli、Binomial、Beta
- Python程序设计题库——第二章
- skype8.34 新版本不能启动/打开
- 言简意赅之二进制运算符口诀
- postgresql 字符串拼接函数concat_lower_or_upper
- svn服务器安装位置,ubuntu下svn服务器安装配置--经过本人测试(非wwj)