Java多线程编程核心技术---Lock的基本概念和使用

Lock接口:

ReentrantLock的基本功能:

  ReentrantLock的lock和unlock方法进行加锁,解锁。可以起到和synchronized关键字一样的效果;

  选择性通知!!!:

           使用Condition实现等待通知,和wait/notifyAll机制一样,要使用await()方法进入WAITING状态,就必须要先使用lock.lock()获得同步监视器。

          

 1 package service;
 2 
 3 import java.util.concurrent.locks.Condition;
 4 import java.util.concurrent.locks.ReentrantLock;
 5 
 6 public class MyService {
 7     private ReentrantLock lock = new ReentrantLock();
 8     private Condition condition = lock.newCondition();
 9 
10     public void waitMethod() {
11         try {
12             lock.lock();
13             System.out.println("A");
14             condition.await();
15             System.out.println("B");
16         } catch (InterruptedException e) {
17             e.printStackTrace();
18         } finally {
19             lock.unlock();
20             System.out.println("锁释放了!");
21         }
22     }
23 }
View Code

  类比wait/notify机制:wait-->await  notify-->signal notifyAll-->signalAll

  选择性通知:使用多个Condition实现

 

package service;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MyService {

    private Lock lock = new ReentrantLock();
        // 使用多个Condition  todo 查看原理
    public Condition conditionA = lock.newCondition();
    public Condition conditionB = lock.newCondition();

    public void awaitA() {
        try {
            lock.lock();
            System.out.println("begin awaitA时间为" + System.currentTimeMillis()
                    + " ThreadName=" + Thread.currentThread().getName());
            conditionA.await();
            System.out.println("  end awaitA时间为" + System.currentTimeMillis()
                    + " ThreadName=" + Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void awaitB() {
        try {
            lock.lock();
            System.out.println("begin awaitB时间为" + System.currentTimeMillis()
                    + " ThreadName=" + Thread.currentThread().getName());
            conditionB.await();
            System.out.println("  end awaitB时间为" + System.currentTimeMillis()
                    + " ThreadName=" + Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void signalAll_A() {
        try {
            lock.lock();
            System.out.println("  signalAll_A时间为" + System.currentTimeMillis()
                    + " ThreadName=" + Thread.currentThread().getName());
            conditionA.signalAll();
        } finally {
            lock.unlock();
        }
    }

    public void signalAll_B() {
        try {
            lock.lock();
            System.out.println("  signalAll_B时间为" + System.currentTimeMillis()
                    + " ThreadName=" + Thread.currentThread().getName());
            conditionB.signalAll();
        } finally {
            lock.unlock();
        }
    }
}
    
View Code

  public ReentrantLock(true) 采用公平策略。反之采用不公平策略。

  tryLock():如果没被锁定,获得锁。否则不获得锁。

  tryLock(long timeout , TimeUnit unit):给宽定时间的tryLock()

 1 package service;
 2 
 3 import java.util.concurrent.locks.ReentrantLock;
 4 
 5 public class MyService {
 6 
 7     public ReentrantLock lock = new ReentrantLock();
 8 
 9     public void waitMethod() {
10         if (lock.tryLock()) {
11             System.out.println(Thread.currentThread().getName() + "获得锁");
12         } else {
13             System.out.println(Thread.currentThread().getName() + "没有获得锁");
14         }
15     }
16 }
View Code
 1 package service;
 2 
 3 import java.util.concurrent.TimeUnit;
 4 import java.util.concurrent.locks.ReentrantLock;
 5 
 6 public class MyService {
 7 
 8     public ReentrantLock lock = new ReentrantLock();
 9 
10     public void waitMethod() {
11         try {
12             if (lock.tryLock(3, TimeUnit.SECONDS)) {
13                 System.out.println("      " + Thread.currentThread().getName()
14                         + "获得锁的时间:" + System.currentTimeMillis());
15                 Thread.sleep(10000);
16             } else {
17                 System.out.println("      " + Thread.currentThread().getName()
18                         + "没有获得锁");
19             }
20         } catch (InterruptedException e) {
21             e.printStackTrace();
22         } finally {
23             if (lock.isHeldByCurrentThread()) {
24                 lock.unlock();
25             }
26         }
27     }
28 }
View Code

 

  使用Codition实现顺序执行

 1 package test.run;
 2 
 3 import java.util.concurrent.locks.Condition;
 4 import java.util.concurrent.locks.ReentrantLock;
 5 
 6 public class Run {
 7 
 8     volatile private static int nextPrintWho = 1;
 9     private static ReentrantLock lock = new ReentrantLock();
10     final private static Condition conditionA = lock.newCondition();
11     final private static Condition conditionB = lock.newCondition();
12     final private static Condition conditionC = lock.newCondition();
13 
14     public static void main(String[] args) {
15 
16         Thread threadA = new Thread() {
17             public void run() {
18                 try {
19                     lock.lock();
20                     while (nextPrintWho != 1) {
21                         conditionA.await();
22                     }
23                     for (int i = 0; i < 3; i++) {
24                         System.out.println("ThreadA " + (i + 1));
25                     }
26                     nextPrintWho = 2;
27                     conditionB.signalAll();
28                 } catch (InterruptedException e) {
29                     e.printStackTrace();
30                 } finally {
31                     lock.unlock();
32                 }
33             }
34         };
35 
36         Thread threadB = new Thread() {
37             public void run() {
38                 try {
39                     lock.lock();
40                     while (nextPrintWho != 2) {
41                         conditionB.await();
42                     }
43                     for (int i = 0; i < 3; i++) {
44                         System.out.println("ThreadB " + (i + 1));
45                     }
46                     nextPrintWho = 3;
47                     conditionC.signalAll();
48                 } catch (InterruptedException e) {
49                     e.printStackTrace();
50                 } finally {
51                     lock.unlock();
52                 }
53             }
54         };
55 
56         Thread threadC = new Thread() {
57             public void run() {
58                 try {
59                     lock.lock();
60                     while (nextPrintWho != 3) {
61                         conditionC.await();
62                     }
63                     for (int i = 0; i < 3; i++) {
64                         System.out.println("ThreadC " + (i + 1));
65                     }
66                     nextPrintWho = 1;
67                     conditionA.signalAll();
68                 } catch (InterruptedException e) {
69                     e.printStackTrace();
70                 } finally {
71                     lock.unlock();
72                 }
73             }
74         };
75         Thread[] aArray = new Thread[5];
76         Thread[] bArray = new Thread[5];
77         Thread[] cArray = new Thread[5];
78 
79         for (int i = 0; i < 5; i++) {
80             aArray[i] = new Thread(threadA);
81             bArray[i] = new Thread(threadB);
82             cArray[i] = new Thread(threadC);
83 
84             aArray[i].start();
85             bArray[i].start();
86             cArray[i].start();
87         }
88 
89     }
90 }
View Code

 

ReentrantReadWriteLock:

  出现目的:ReentrantLock完全互斥排他,效率低下。

  改善:ReentrantReadWriteLock 读写锁。只要有写操作就是互斥的,没有写操作,就是共享的。

  

 1 package service;
 2 
 3 import java.util.concurrent.locks.ReentrantReadWriteLock;
 4 
 5 
 6 /*
 7 output:时间差为10000
 8 
 9 */
10 
11 public class Service {
12 
13     private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
14 
15     public void read() {
16         try {
17             try {
18                 lock.readLock().lock();
19                 System.out.println("获得读锁" + Thread.currentThread().getName()
20                         + " " + System.currentTimeMillis());
21                 Thread.sleep(10000);
22             } finally {
23                 lock.readLock().unlock();
24             }
25         } catch (InterruptedException e) {
26             e.printStackTrace();
27         }
28     }
29 
30     public void write() {
31         try {
32             try {
33                 lock.writeLock().lock();
34                 System.out.println("获得写锁" + Thread.currentThread().getName()
35                         + " " + System.currentTimeMillis());
36                 Thread.sleep(10000);
37             } finally {
38                 lock.writeLock().unlock();
39             }
40         } catch (InterruptedException e) {
41             e.printStackTrace();
42         }
43     }
44 
45 }
View Code

 

posted @ 2018-01-31 23:22  rose^Chen  阅读(224)  评论(0编辑  收藏  举报