我想很多购买了《Java程序员面试宝典》
问:请对比synchronized与java.util.
答案:主要相同点:
主要不同点:
恩,让我们先鄙视一下应试教育。
言归正传,我们先来看一个多线程程序。
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
--> public class ThreadDemo implements Runnable {
class Student {
private int age = 0 ;
public int getAge() {
return age;
}
public void setAge( int age) {
this .age = age;
}
}
Student student = new Student();
int count = 0 ;
public static void main(String[] args) {
ThreadDemo td = new ThreadDemo();
Thread t1 = new Thread(td, " a " );
Thread t2 = new Thread(td, " b " );
Thread t3 = new Thread(td, " c " );
t1.start();
t2.start();
t3.start();
}
public void run() {
accessStudent();
}
public void accessStudent() {
String currentThreadName = Thread.currentThread().getName();
System.out.println(currentThreadName + " is running! " );
synchronized ( this ) { // (1)使用同一个ThreadDemo对象作为同步锁
System.out.println(currentThreadName + " got lock1@Step1! " );
try {
count ++ ;
Thread.sleep( 5000 );
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println(currentThreadName + " first Reading count: " + count);
}
}
System.out.println(currentThreadName + " release lock1@Step1! " );
synchronized ( this ) { // (2)使用同一个ThreadDemo对象作为同步锁
System.out.println(currentThreadName + " got lock2@Step2! " );
try {
Random random = new Random();
int age = random.nextInt( 100 );
System.out.println( " thread " + currentThreadName + " set age to: " + age);
this .student.setAge(age);
System.out.println( " thread " + currentThreadName + " first read age is: " + this .student.getAge());
Thread.sleep( 5000 );
} catch (Exception ex) {
ex.printStackTrace();
} finally {
System.out.println( " thread " + currentThreadName + " second read age is: " + this .student.getAge());
}
}
System.out.println(currentThreadName + " release lock2@Step2! " );
}
}
运行结果:
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
--> a is running!
a got lock1@Step1!
b is running!
c is running!
a first Reading count: 1
a release lock1@Step1!
a got lock2@Step2!
thread a set age to: 76
thread a first read age is: 76
thread a second read age is: 76
a release lock2@Step2!
c got lock1@Step1!
c first Reading count: 2
c release lock1@Step1!
c got lock2@Step2!
thread c set age to: 35
thread c first read age is: 35
thread c second read age is: 35
c release lock2@Step2!
b got lock1@Step1!
b first Reading count: 3
b release lock1@Step1!
b got lock2@Step2!
thread b set age to: 91
thread b first read age is: 91
thread b second read age is: 91
b release lock2@Step2!
成功生成(总时间: 30 秒)
显然,在这个程序中,
转载注明出处:http://x- spirit.javaeye.com/、http: //www.blogjava.net/zhangwei217245/
我想一定有人会说:
那么好。我们把第二个同步块中的对象锁改为student(
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
--> a is running!
a got lock1@Step1!
b is running!
c is running!
a first Reading count: 1
a release lock1@Step1!
a got lock2@Step2!
thread a set age to: 73
thread a first read age is: 73
c got lock1@Step1!
thread a second read age is: 73
a release lock2@Step2!
c first Reading count: 2
c release lock1@Step1!
c got lock2@Step2!
thread c set age to: 15
thread c first read age is: 15
b got lock1@Step1!
thread c second read age is: 15
c release lock2@Step2!
b first Reading count: 3
b release lock1@Step1!
b got lock2@Step2!
thread b set age to: 19
thread b first read age is: 19
thread b second read age is: 19
b release lock2@Step2!
成功生成(总时间: 21 秒)
从修改后的运行结果来看,显然,由于同步块的对象锁不同了,
转载注明出处:http://x- spirit.javaeye.com/、http: //www.blogjava.net/zhangwei217245/
可见,使用不同的对象锁,在不同的同步块中完成任务,
很多人看到这不禁要问:这和新的Lock框架有什么关系?
别着急。我们这就来看一看。
synchronized块的确不错,
1. 它无法中断一个正在等候获得锁的线程,
2.
转载注明出处:http://x- spirit.javaeye.com/、http: //www.blogjava.net/zhangwei217245/
java.util.concurrent.lock 中的 Lock 框架是锁定的一个抽象,它允许把锁定的实现作为 Java 类,而不是作为语言的特性来实现。这就为 Lock 的多种实现留下了空间,各种实现可能有不同的调度算法、
JDK 官方文档中提到:
ReentrantLock是“一个可重入的互斥锁 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,
ReentrantLock 将由最近成功获得锁,并且还没有释放该锁的线程所拥有。
简单来说,
转载注明出处:http://x- spirit.javaeye.com/、http: //www.blogjava.net/zhangwei217245/
ReentrantLock 类(重入锁)实现了 Lock ,它拥有与 synchronized 相同的并发性和内存语义,但是添加了类似锁投票、
我们把上面的例程改造一下:
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
--> public class ThreadDemo implements Runnable {
class Student {
private int age = 0 ;
public int getAge() {
return age;
}
public void setAge( int age) {
this .age = age;
}
}
Student student = new Student();
int count = 0 ;
ReentrantLock lock1 = new ReentrantLock(false);
ReentrantLock lock2 = new ReentrantLock(false );
public static void main(String[] args) {
ThreadDemo td = new ThreadDemo();
for ( int i = 1 ; i <= 3 ; i ++ ) {
Thread t = new Thread(td, i + "" );
t.start();
}
}
public void run() {
accessStudent();
}
public void accessStudent() {
String currentThreadName = Thread.currentThread().getName();
System.out.println(currentThreadName + " is running! " );
lock1.lock(); // 使用重入锁
System.out.println(currentThreadName + " got lock1@Step1! " );
try {
count ++ ;
Thread.sleep( 5000 );
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println(currentThreadName + " first Reading count: " + count);
lock1.unlock();
System.out.println(currentThreadName + " release lock1@Step1! " );
}
lock2.lock(); // 使用另外一个不同的重入锁
System.out.println(currentThreadName + " got lock2@Step2! " );
try {
Random random = new Random();
int age = random.nextInt( 100 );
System.out.println( " thread " + currentThreadName + " set age to: " + age);
this .student.setAge(age);
System.out.println( " thread " + currentThreadName + " first read age is: " + this .student.getAge());
Thread.sleep( 5000 );
} catch (Exception ex) {
ex.printStackTrace();
} finally {
System.out.println( " thread " + currentThreadName + " second read age is: " + this .student.getAge());
lock2.unlock();
System.out.println(currentThreadName + " release lock2@Step2! " );
}
}
}
从上面这个程序我们看到:
对象锁的获得和释放是由手工编码完成的,
这说明两点问题:
1. 新的ReentrantLock的确实现了和同步块相同的语义功
2. 使用新的ReentrantLock,
3. 使用新的ReentrantLock,
转载注明出处:http://x- spirit.javaeye.com/、http: //www.blogjava.net/zhangwei217245/
细心的读者又发现了:
在我们的例程中,创建ReentrantLock实例的时候,
转载注明出处:http://x- spirit.javaeye.com/、http: //www.blogjava.net/zhangwei217245/
转载注明出处:http://x- spirit.javaeye.com/、http: //www.blogjava.net/zhangwei217245/