黑马程序员技术交流社区

标题: static 的 synchronized 方法和synchronized 块的应用 [打印本页]

作者: 崔仁军    时间: 2012-4-28 20:15
标题: static 的 synchronized 方法和synchronized 块的应用

如果某个 synchronized  方法是 static 的,那么当线程访问该方法时,它锁的并不是synchronized 方法所在的对象,而是synchronized 方法所在的对象所对应的Class 对象,因为Java  中无论一个类有多少个对象,这些对象会对应唯一一个Class 对象,因此当线程分别访问同一个类的两个对象的两个 static,synchronized 方法时,他们的执行顺序也是顺序的,也就是说一个线程先去执行方法,执行完毕后另一个线程才开始执行。
2  synchronized 方法是一种粗粒度的并发控制,某一时刻,只能有一个线程执行该synchronized 方法;    synchronized 块则是一种细粒度的并发控制,只会将块中的代码同步,位于方法内、synchronized 块之外的代码是可以被多个线程同时访问到的。

作者: 岳伟伟    时间: 2012-4-28 21:50
不管是同步代码块,还是同步函数,静态同步函数,在运行这些封装内容的时候,都会先”监视“一个对象。在调用同一个类的所有静态同步方法时,会监视类名.class这个对象,这个类所有的静态同步方法都是同步的~,即使这个类有100个静态方法,如果都被synchronized同步,同一时间只能执行一个。
不仅如此,如果这个类内某个同步代码块的锁被定为 类名.class,同步代码块内的代码与所有的静态同步方法就是同步的。如果这个类内某个同步代码块的锁被定为 this,同步代码块内的代码与所有的非静态同步方法就是同步的。
作者: 周海诚    时间: 2012-4-29 10:16
本帖最后由 周海诚 于 2012-4-29 10:17 编辑

相对较完整的理解:
synchronized 方法:通过在方法声明中加入 synchronized关键字来声明 synchronized 方法。如:
public synchronized void accessVal(int newVal);
synchronized 方法控制对类成员变量的访问:每个类实例对应一把锁,
每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执行,
否则所属线程阻塞,方法一旦执行,就独占该锁,
直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,
重新进入可执行状态。这种机制确保了同一时刻对于每一个类实例,
其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态
(因为至多只有一个能够获得该类实例对应的锁),
从而有效避免了类成员变量的访问冲突
(只要所有可能访问类成员变量的方法均被声明为 synchronized)。
在 Java 中,不光是类实例,每一个类也对应一把锁,
这样我们也可将类的静态成员函数声明为 synchronized ,
以控制其对类的静态成员变量的访问。
synchronized 方法的缺陷:若将一个大的方法声明为synchronized 将会大大影响效率,
典型地,若将线程类的方法 run() 声明为 synchronized ,由于在线程的整个生命期内它一直在运行
,因此将导致它对本类任何 synchronized 方法的调用都永远不会成功。
当然我们可以通过将访问类成员变量的代码放到专门的方法中,将其声明为 synchronized ,
并在主方法中调用来解决这一问题,但是 Java 为我们提供了更好的解决办法,
那就是 synchronized 块。
2. synchronized 块:通过 synchronized关键字来声明synchronized 块。语法如下:
synchronized(syncObject) {
//允许访问控制的代码
}
synchronized 块是这样一个代码块,其中的代码必须获得对象 syncObject
如前所述,可以是类实例或类的锁方能执行,具体机制同前所述。
由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2