java synchronized详解(一)
引出:三个线程分别锁定this , obj1 , obj2 三个对象,请运行此代码查看打印结果。
class Food {
int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
class Resource2 {
int limit = 1000;
private Food obj1 = new Food();
private Food obj2 = new Food();
public synchronized void f() {//锁定this
for (int i = 0; i < limit; i++) {
//修改obj1
obj1.setId(i);
//修改obj2
obj2.setId(i);
System.out.println(" this ");
}
}
public void g() {
synchronized (obj1) {
for (int i = 0; i < limit; i++) {
if (i != 0 && obj1.getId() != (i - 1)) {
//说明g方法和f方法都可以对obj1进行操作,会出现线程安全问题
System.err.println("obj1 --- " + "i:" + i + " , id:" + obj1.getId());
}
//修改obj1
obj1.setId(i);
System.out.println(" obj1 ");
}
}
}
public void h() {
synchronized (obj2) {
for (int i = 0; i < limit; i++) {
if (i != 0 && obj2.getId() != (i - 1)) {
//说明h方法和f方法都可以对obj2进行操作,会出现线程安全问题
System.err.println("obj2 --- " + "i:" + i + " , id:" + obj2.getId());
}
//修改obj2
obj2.setId(i);
System.out.println(" obj2 ");
}
}
}
}
/**
* Created on 2013-8-28
* <p>Discription:从打印的结果可以看出三个线程执行三个方法,锁定不同的对象,三个方法同时在运行,不会出现某一个线程等待某个对象的锁的情况</p>
* @return void
*/
public class Demo{
public static void main(String[] args) {
final Resource2 rs = new Resource2();
new Thread() {
public void run() {
rs.f();
}
}.start();
new Thread() {
public void run() {
rs.g();
}
}.start();
new Thread() {
public void run() {
rs.h();
}
}.start();
}
}
从打印的结果可以看出三个线程执行三个方法,锁定不同的对象,三个方法同时在运行,不会出现某一个线程等待某个对象的锁的情况 。
java synchronized详解:
**
记下来,很重要。
**
Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
五、以上规则对其它对象锁同样适用.
六、 synchronized关键字是不能继承的,也就是说,基类的方法synchronized f(){} 在继承类中并不自动是synchronized f(){},而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法;