【java】synchronized 关键字
2016-05-30 16:12
344 查看
大一的时候对这个东西敬而远之,可能是因为刚学java,完全不理解,现在是时候搞清楚它了。
字面意思是同步,翻译过来挺绕的。从同步和异步这对概念来入手,是比较难理解的。其实只要围绕“互斥”这个概念,synchronized关键字就很好理解!
大二操作系统会介绍互斥的概念,与java中的含义完全相同,只不过一个是操作系统中的,一个是java jvm的,应用层次不同而已。
1.我理解的java中的互斥是,在多线程环境下,对同一数据进行更新操作的互斥,也即只有当一个线程执行完更新后,另一个线程才可以开始。这也是synchronized关键字的用处。
举个例子,老生常谈了,存钱的例子。比如A的账户是100,现准备在atm中存入100,在这个过程中,A的朋友正在用手机银行,也试图往A的账户存入100。那么,在理论上就会有一个t1时刻,在t1时刻,atm机获取了A账户余额100,还未加100,同时A友的手机银行后台也获取了余额100,然后再各自进行加100的操作,更新A的账户,可想而知,A最后只有200,而非300。
问题出在对账户的更新必须互斥,atm在更新的时候,其他方式就必须等待,atm更新完了,才能开始其他的更新操作。这就是互斥。
2.锁的概念。这也是synchronized用法中的一个关键点。锁其实是互斥的标志。定义了哪些更新操作需要互斥。比如在A更新时,B的账户更新就不应该被阻塞,A和B的账户更新完全没有关系。而A的atm更新就应该和A的手机银行更新互斥。所以,锁定义了互斥的条件。
java中的锁
方法锁:
在非static方法上加synchronized关键字,那么同一个对象的所有的带有synchronized的方法全部互斥;锁就是调用的对象。所有的线程要想调用这个方法,必须拿到该对象的锁,锁只能被一个线程拥有。
块锁:
锁一段代码,需要指定锁是什么,可以是类锁可以使对象锁。块锁的优势是可以精确锁的范围,提高性能。
静态方法锁:
只能应用于静态方法,线程需要拿到类的锁才可以执行,不同对象也会被互斥。
例子:
最后打印结果的时候,需要等待的原因是打印语句执行时,可能之前的更新线程还未全部执行完毕。
推荐一篇很好的博客:http://www.cnblogs.com/paddix/p/5367116.html
字面意思是同步,翻译过来挺绕的。从同步和异步这对概念来入手,是比较难理解的。其实只要围绕“互斥”这个概念,synchronized关键字就很好理解!
大二操作系统会介绍互斥的概念,与java中的含义完全相同,只不过一个是操作系统中的,一个是java jvm的,应用层次不同而已。
1.我理解的java中的互斥是,在多线程环境下,对同一数据进行更新操作的互斥,也即只有当一个线程执行完更新后,另一个线程才可以开始。这也是synchronized关键字的用处。
举个例子,老生常谈了,存钱的例子。比如A的账户是100,现准备在atm中存入100,在这个过程中,A的朋友正在用手机银行,也试图往A的账户存入100。那么,在理论上就会有一个t1时刻,在t1时刻,atm机获取了A账户余额100,还未加100,同时A友的手机银行后台也获取了余额100,然后再各自进行加100的操作,更新A的账户,可想而知,A最后只有200,而非300。
问题出在对账户的更新必须互斥,atm在更新的时候,其他方式就必须等待,atm更新完了,才能开始其他的更新操作。这就是互斥。
2.锁的概念。这也是synchronized用法中的一个关键点。锁其实是互斥的标志。定义了哪些更新操作需要互斥。比如在A更新时,B的账户更新就不应该被阻塞,A和B的账户更新完全没有关系。而A的atm更新就应该和A的手机银行更新互斥。所以,锁定义了互斥的条件。
java中的锁
方法锁:
在非static方法上加synchronized关键字,那么同一个对象的所有的带有synchronized的方法全部互斥;锁就是调用的对象。所有的线程要想调用这个方法,必须拿到该对象的锁,锁只能被一个线程拥有。
块锁:
锁一段代码,需要指定锁是什么,可以是类锁可以使对象锁。块锁的优势是可以精确锁的范围,提高性能。
静态方法锁:
只能应用于静态方法,线程需要拿到类的锁才可以执行,不同对象也会被互斥。
例子:
package main; public class Main { public static void main(String[] args) { new Main().f(); } public void f(){ final Acount acount1 = new Acount(); for(int j=0;j<10;j++){ Thread thread = new Thread(new Runnable() { @Override public void run() { acount1.add1(100); } }); thread.start(); } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("1结果: "+acount1.getMoney()); } }
package main; public class Acount{ private int money = 0; public synchronized void add(int inc){ System.out.println("*********开始********"); int temp = this.money; temp = temp + inc; this.money = temp; System.out.println(money); System.out.println("*********结束********"); } public void add1(int inc){ synchronized (this) { System.out.println("*********开始********"); int temp = this.money; temp = temp + inc; this.money = temp; System.out.println(money); System.out.println("*********结束********"); } } public int getMoney() { return money; } }
最后打印结果的时候,需要等待的原因是打印语句执行时,可能之前的更新线程还未全部执行完毕。
推荐一篇很好的博客:http://www.cnblogs.com/paddix/p/5367116.html
相关文章推荐
- Java8新特性(四)------接口中可以定义方法体
- JAVA进阶书籍
- Java中switch支持的数据类型
- eclipse/STS导入maven项目后,IDE中不显示svn信息
- MyEclipse:(2)用正则表达式替换
- java回忆录——接口回调机制(1)
- hihocoder 1069最近公共祖先(DFS + ST)java实现
- MyEclipse 快捷键
- java中的多线程(二)
- Java工具类实现校验公民身份证的有效性
- springmvc默认首页问题
- Struts2源码分析
- Java8新特性(三)------Stream
- JAVA 接口 Interface 学习笔记 implements
- java获得指定日期的前一天,后一天的代码
- java防止sql注入
- springmvc的ModelAttribute注解,在controller每个方法执行前被执行
- Java多线程学习(吐血超详细总结)
- Java集合排序,针对多个字段排序
- Java8新特性(二)------lamda表达式