Java 多线程(六) synchronized关键字详解
2015-11-11 15:34
316 查看
多线程的同步机制对资源进行加锁,使得在同一个时间,只有一个线程可以进行操作,同步用以解决多个线程同时访问时可能出现的问题。
同步机制可以使用synchronized关键字实现。
当synchronized关键字修饰一个方法的时候,该方法叫做同步方法。
当synchronized方法执行完或发生异常时,会自动释放锁。
下面通过一个例子来对synchronized关键字的用法进行解析。
View Code
例子程序4所达到的效果和例子程序2的效果一样,都是使得两个线程的执行顺序进行,而不是并发进行,当一个线程执行时,将object对象锁住,另一个线程就不能执行对应的块。
synchronized方法实际上等同于用一个synchronized块包住方法中的所有语句,然后在synchronized块的括号中传入this关键字。当然,如果是静态方法,需要锁定的则是class对象。
可能一个方法中只有几行代码会涉及到线程同步问题,所以synchronized块比synchronized方法更加细粒度地控制了多个线程的访问,只有synchronized块中的内容不能同时被多个线程所访问,方法中的其他语句仍然可以同时被多个线程所访问(包括synchronized块之前的和之后的)。
注意:被synchronized保护的数据应该是私有的。
结论:
synchronized方法是一种粗粒度的并发控制,某一时刻,只能有一个线程执行该synchronized方法;
synchronized块则是一种细粒度的并发控制,只会将块中的代码同步,位于方法内、synchronized块之外的其他代码是可以被多个线程同时访问到的。
JDK1.4及之前是无法避免这些问题的。
JDK 5.0引入了这样一个包:java.util.concurrent:
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-frame.html
专门解决这一问题。
限于篇幅,这里不再介绍。
同步机制可以使用synchronized关键字实现。
当synchronized关键字修饰一个方法的时候,该方法叫做同步方法。
当synchronized方法执行完或发生异常时,会自动释放锁。
下面通过一个例子来对synchronized关键字的用法进行解析。
public class ThreadTest { public static void main(String[] args) { Example example = new Example(); Thread t1 = new Thread1(example); Thread t2 = new Thread2(example); t1.start(); t2.start(); } } class Example { private Object object = new Object(); public void execute() { synchronized (object) { for (int i = 0; i < 20; ++i) { try { Thread.sleep((long) Math.random() * 1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Hello: " + i); } } } public void execute2() { synchronized (object) { for (int i = 0; i < 20; ++i) { try { Thread.sleep((long) Math.random() * 1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("World: " + i); } } } } class Thread1 extends Thread { private Example example; public Thread1(Example example) { this.example = example; } @Override public void run() { example.execute(); } } class Thread2 extends Thread { private Example example; public Thread2(Example example) { this.example = example; } @Override public void run() { example.execute2(); } }
View Code
例子程序4所达到的效果和例子程序2的效果一样,都是使得两个线程的执行顺序进行,而不是并发进行,当一个线程执行时,将object对象锁住,另一个线程就不能执行对应的块。
synchronized方法实际上等同于用一个synchronized块包住方法中的所有语句,然后在synchronized块的括号中传入this关键字。当然,如果是静态方法,需要锁定的则是class对象。
可能一个方法中只有几行代码会涉及到线程同步问题,所以synchronized块比synchronized方法更加细粒度地控制了多个线程的访问,只有synchronized块中的内容不能同时被多个线程所访问,方法中的其他语句仍然可以同时被多个线程所访问(包括synchronized块之前的和之后的)。
注意:被synchronized保护的数据应该是私有的。
结论:
synchronized方法是一种粗粒度的并发控制,某一时刻,只能有一个线程执行该synchronized方法;
synchronized块则是一种细粒度的并发控制,只会将块中的代码同步,位于方法内、synchronized块之外的其他代码是可以被多个线程同时访问到的。
JDK 5.0的并发包
使用synchronized关键字解决线程的同步问题会带来一些执行效率上的问题。JDK1.4及之前是无法避免这些问题的。
JDK 5.0引入了这样一个包:java.util.concurrent:
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-frame.html
专门解决这一问题。
限于篇幅,这里不再介绍。
参考资料
圣思园张龙老师Java SE系列视频教程。相关文章推荐
- Spring AOP编程(XML实现)
- javac编译的过程
- JAVA Properties类的使用
- Eclipse中调试Android技巧
- 深入理解Java:注解(Annotation)自定义注解入门
- 如何在eclipse jee中创建Maven project并且转换为Dynamic web project
- spring 集成shiro 之 自定义过滤器
- 从”JAVA“而终 17:java Jdbc编程
- SpringMVC 返回JSON数据
- JAVA 实现Timestamp和String的相互转换
- Java学习笔记(五)接口及类
- myeclipse安装svn插件的多种方式
- 解决javaWEB中前后台中文乱码问题的3种方法
- Groovy 循环语法
- Spring MVC常用的注解
- 深入理解Java4:Singleton单例模式七种方式
- Java学习笔记(四)修饰符及访问权限
- java集合类TreeMap和TreeSet及红黑树
- struts2中的日期期输入显示问题
- Java汉字转换为拼音