在JDK5的并发包中有一个子包为java.concurrent.locks,它下面定义了三个接口Lock,ReadWriteLock,Condition,分别为重入锁,读写锁,锁条件判断
LOCK:
Lock与java关键字(synchronized)具有相同的功能,但它更加灵活。ReentrantLock作为Lock接口的实现类,被作为Java语言中synchronized功能的替代,它们具有相同的内存意义,相同的锁定,但在争用条件下却有更好的性能,此为它还有synchronized没有提供的其它特性。但就实际应用来说,由于内部锁是内置于Java虚拟机中的,它能够进行优化,因此未来的性能改进可能更倾向于内部锁,而不是重入锁。综上所述,除非你的应用程序需要发在Java 5.0上,或者需要使用重入锁的可伸缩性,否则就应该选择内部锁。
总之,ReentrantLock锁与Java内在锁相比有下面的特点:
1)ReentrantLock必须在 finally 块中释放锁,而使用synchronized同步,JVM 将确保锁会获得自动释放。
2)与目前的 synchronized 实现相比,争用下的 ReentrantLock 实现更具可伸缩性。
3)对于ReentrantLock ,可以有不止一个条件变量与它关联。(Condition后面会说到)
4)允许选择想要一个公平锁,还是一个不公平锁。(new ReentrantLock(false)非公平锁,非公平锁执行效率会更高)
5)除非你对 Lock 的某个高级特性有明确的需要,或者有明确的证据表明在特定情况下,同步已经成为可伸缩性的瓶颈,否则还是应当继续使用synchronized。
6)Lock 类只是普通的类,JVM 不知道具体哪个线程拥有 Lock 对象。而且,几乎每个开发人员都熟悉 synchronized,它可以在 JVM 的所有版本中工作。
Condition:
类似于java中原来线程交互所用的wait,notify和notifyAll方法在新的并发包中基于重入锁机制引入了Condition接口,Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set(wait-set),就是多路等待。Condition 的方法与 wait 、notify 和 notifyAll 方法类似,分别命名为 await 、 signal和singalAll因为它们不能覆盖Object上的对应方法。
下面是一个多路条件等待按顺序执行的例子,给定一个0,按1,2,3,这样的顺序依次加一次,总共加10次,并输出每次加后的结果,模拟让多线程来做:
1 importjava.util.concurrent.locks.Condition;
2 importjava.util.concurrent.locks.Lock;
3 importjava.util.concurrent.locks.ReentrantLock;
4
5 public classConditionTest {
6
7 /**
8 * @paramargs
9 */
10 public static voidmain(String[] args) {
11 for (int i = 0; i < 10; i++) {
12 new Thread(newRunnable() {
13
14 @Override
15 public voidrun() {
16 newTest1().sub1();
17
18 }
19 }).start();
20
21 new Thread(newRunnable() {
22
23 @Override
24 public voidrun() {
25 newTest1().sub2();
26
27 }
28 }).start();
29
30 new Thread(newRunnable() {
31
32 @Override
33 public voidrun() {
34 newTest1().sub3();
35
36 }
37 }).start();
38 }
39 }
40
41 }
42
43 classTest1 {
44 public static int i = 0;
45 public static int conNum = 1;
46 //此处注意锁和condition也要定义成静态的,不然就有多把锁和condition了,相当于没加一样。
47 public static Lock lock = new ReentrantLock(false);
48 public static Condition con1 =lock.newCondition();
49 public static Condition con2 =lock.newCondition();
50 public static Condition con3 =lock.newCondition();
51
52 //方法1对i进行加1
53 public voidsub1() {
54 lock.lock();
55 try{
56 while (conNum != 1) {
57 try{
58 con1.await();
59 } catch(InterruptedException e) {
60 e.printStackTrace();
61 }
62 }
63 i++;
64 System.out.print(i + ",");
65 conNum = 2;
66 con2.signal();
67 } finally{
68 lock.unlock();
69 }
70
71 }
72
73 //方法2对i加2
74 public voidsub2() {
75 lock.lock();
76
77 try{
78 while (conNum != 2) {
79 try{
80 con2.await();
81 } catch(InterruptedException e) {
82 e.printStackTrace();
83 }
84 }
85 i = i + 2;
86 System.out.print(i + ",");
87 conNum = 3;
88 con3.signal();
89 } finally{
90 lock.unlock();
91 }
92
93 }
94
95 //方法3对i加3;
96 public voidsub3() {
97 lock.lock();
98 try{
99