为什么Synchronized block要使用this作同步
来源:互联网 发布:linux 命令抓包 编辑:程序博客网 时间:2024/05/22 16:55
为什么Synchronized block要使用this作同步
学Java并发编程时遇到过一个问题:为什么凡是涉及到Synchronized block的代码,总是使用synchronized(this)这样的代码。一开始很疑惑不解,既然Synchronized block可以通过获得对象的锁来使得多个线程对同一对象的访问同步,那么Synchronized block可以使用任何对象(比如成员变量)来作同步,而为什么偏偏使用this来做同步呢?后来经过一番思索想同了其中的奥妙:如果使用其他对象来做同步,会产生线程不安全。先看如下一段代码:
package concurrent;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
class Testee {
private Integer i = new Integer(1);
public void f() {
synchronized (i) {
System.out.println(Thread.currentThread().getName() + " get i = "
+ i);
System.out.println(Thread.currentThread().getName()
+ " change i = new Integer(2)");
i = new Integer(2);
try {
System.out.println(Thread.currentThread().getName()
+ " Sleep 2 sec");
TimeUnit.SECONDS.sleep(2); // 保证Thread#2获得新的i的锁
System.out.println(Thread.currentThread().getName()
+ " Sleep finished");
System.out.println(Thread.currentThread().getName()
+ " get i = " + i + " again");
} catch (InterruptedException e) {
}
}
}
public void g() {
// 先睡1秒,保证Thread#1完成对i的重新赋值工作
try {
TimeUnit.SECONDS.sleep(1);
synchronized (i) {
System.out.println(Thread.currentThread().getName()
+ " get i = " + i);
System.out.println(Thread.currentThread().getName()
+ " Sleep 2 sec");
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName()
+ " Sleep finished");
}
} catch (InterruptedException e) {
}
}
}
public class CriticalSectionTest {
public static void main(String[] args) {
final Testee testee = new Testee();
Thread t1 = new Thread("Thread#1") {
public void run() {
testee.f();
}
};
Thread t2 = new Thread("Thread#2") {
public void run() {
testee.g();
}
};
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(t1);
exec.execute(t2);
exec.shutdown();
}
}
Output:
pool-1-thread-1 change i = new Integer(2)
pool-1-thread-1 Sleep 2 sec
pool-1-thread-2 get i = 2
pool-1-thread-2 Sleep 2 sec
pool-1-thread-1 Sleep finished
pool-1-thread-1 get i = 2 again
pool-1-thread-2 Sleep finished可以看到,Testee类的f()方法和g()方法是通过其内部成员Integer i来做同步的,在本例中f()方法和g()方法分别在Thread#1和Thread#2中调用。Thread#2先sleep 2秒以保证Thread#1首先获得i的锁,然后Thread#1对i做了一件很危险的事情,Thread#1把i指向了一个新的Integer对象,接着Thread#1就去睡了2秒。此时Thread#2醒来,立即获得了i的锁(此时的i引用的是新的对象),然后它啥事情也没做又去睡了2秒。当Thread#1醒来时,它也可以立即获得(从它在Thread#2醒来之前就能够获得i看出),因为它之前同步的i和这次获得的i不是同一个对象。结果就是,经过Thread#1一开始的给i重新赋值的操作,两个线程对i的操作都不安全了,因为实际上两个线程的synchronized block所用的对象根本就是两个对象。
所以,在很多使用synchronized block的代码中,都使用this来作同步,因为this是不可重新赋值的,也就避免了上面例子的问题。
- 为什么Synchronized block要使用this作同步
- Synchronized (同步) block使用实例
- Java同步块(synchronized block)使用详解
- 使用synchronized同步
- block为什么使用copy
- Java同步机制浅谈 synchronized对代码作何影响?
- java 同步机制浅谈-----synchronized对代码作何影响?
- 浅谈Java同步机制synchronized对代码作何影响?
- 同步方法与同步块synchronized(this)详解
- 同步方法与同步块synchronized(this)详解
- 同步方法与同步块synchronized(this)详解
- 使用synchronized块同步方法..
- 使用Synchronized块同步方法
- 使用Synchronized块同步变量
- 使用Synchronized块同步方法
- 使用Synchronized块同步方法
- 使用Synchronized块同步变量
- 使用synchronized实现同步方法
- C++中的空类,默认产生的类成员函数
- mysql安装并实验成功,记录遇见的问题
- 中美教材看两国教育
- 无线互联 嵌入式系统设计的新挑战
- 伟大的程序员同志们累了看看我这笑话,巨搞笑!
- 为什么Synchronized block要使用this作同步
- 清明节的最后的半个小时
- 君子堂介绍
- 【译】《GPU GEMS 3》----Next-Generation SpeedTree Rendering 翻译[1]
- MFC新的生机
- java中的System.in
- 开篇-2009-04-04
- 我也来写一篇吧
- 婚姻