synchronized是Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
五、以上规则对其它对象锁同样适用.
1、synchronized关键字的作用域有二种:
1)是某个对象实例内,synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法(如果一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法)。这时,不同的对象实例的synchronized方法是不相干扰的。也就是说,其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法;
2)是某个类的范围,synchronized static aStaticMethod{}防止多个线程同时访问这个类中的synchronized static 方法。它可以对类的所有对象实例起作用。
2、除了方法前用synchronized关键字,synchronized关键字还可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。用法是: synchronized(this){/*区块*/},它的作用域是当前对象;
3、synchronized关键字是不能继承的,也就是说,基类的方法synchronized f(){} 在继承类中并不自动是synchronized f(){},而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法;
synchronized 方法的缺陷:若将一个大的方法声明为synchronized 将会大大影响效率,典型地,若将线程类的方法 run() 声明为
synchronized ,由于在线程的整个生命期内它一直在运行,因此将导致它对本类任何 synchronized 方法的调用都永远不会成功。当然我们可
以通过将访问类成员变量的代码放到专门的方法中,将其声明为 synchronized ,并在主方法中调用来解决这一问题,但是 Java 为我们提供
了更好的解决办法,那就是 synchronized 块。
2. synchronized 块:通过 synchronized关键字来声明synchronized 块。语法如下:
synchronized(syncObject) {
//允许访问控制的代码
}
synchronized 块是这样一个代码块,其中的代码必须获得对象 syncObject (如前所述,可以是类实例或类)的锁方能执行,具体机
制同前所述。由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。
下面将用代码来实践
/* * **************************************************************************** * 源文件名: cn.com.thread.SynchronizedTest.java * 功能: smart框架 * 版本: @version 1.0 * 编制日期: 2014-4-12 下午12:49:25 * 修改历史: (主要历史变动原因及说明) * YYYY-MM-DD | Author | Change Description * 2014-4-12 | gaowenming | Created */ package cn.com.thread; /** * Description: <类功能描述>. <br> * <p> * <使用说明> * </p> * Makedate:2014-4-12 下午12:49:25 * * @author gaowenming * @version V1.0 */ public class SynchronizedTest { /** * 描述 : <描述函数实现的功能>. <br> * <p> * <使用方法说明> * </p> * * @param args */ public static void main(String[] args) { final PrintNumber pn = new PrintNumber(); // 第一个线程 new Thread(new Runnable() { @Override public void run() { pn.print100(); } }).start(); // 第二个线程 new Thread(new Runnable() { @Override public void run() { pn.print10(); } }).start(); } } /** * * * @Description: 定义一个类,里面有2个方法 * @author gaowenming * @date 2014-4-12 下午12:49:58 * */ class PrintNumber { /** * * 描述 : <从1打印到10>. <br> * <p> * <使用方法说明> * </p> */ public void print10() { for (int i = 1; i <= 10; i++) { System.out.println("print10==================== " + i); } } /** * * 描述 : <从1打印到100>. <br> * <p> * <使用方法说明> * </p> */ public void print100() { for (int i = 1; i <= 100; i++) { System.out.println("print100==================== " + i); } } }
在PrintNumber类中定义了2个方法,一个是从1打印到10,另一个是从1打印到100,现在要求2个方法在执行的过程中互不干扰,在没有加synchronized的情况下,执行结果
print100==================== 1
print10==================== 1
print100==================== 2
print10==================== 2
print100==================== 3
print10==================== 3
print100==================== 4
print10==================== 4
print100==================== 5
print100==================== 6
print100==================== 7
print100==================== 8
print100==================== 9
print100==================== 10
print10==================== 5
print100==================== 11
print10==================== 6
print10==================== 7
print10==================== 8
print10==================== 9
print10==================== 10
很明显2个方法已经在同时执行了,那么加上synchronized后,
.
......
print100==================== 90
print100==================== 91
print100==================== 92
print100==================== 93
print100==================== 94
print100==================== 95
print100==================== 96
print100==================== 97
print100==================== 98
print100==================== 99
print100==================== 100
print10==================== 1
print10==================== 2
print10==================== 3
print10==================== 4
print10==================== 5
print10==================== 6
print10==================== 7
print10==================== 8
print10==================== 9
print10==================== 10