Java ReentrantLock,ReentrantReadWriteLock和Condition的简单描述示例

java.util.concurrent.lock 框架是 JDK5.0 后新增的特性,作用呢是准备用来替代 synchronized 语义和 volatile 声明,属于高帅富性能,对于初级开发来说平时开发可能用不上,因为synchronized 已能很好的应用于大部分场景。如果你的项目里的多线程模块需要用更高的性能,更高的灵活性,更好的伸缩性,那么可以把原来的synchronized块替换成lock框架下的 ReetrantLock, ReetantReadWriteLock,Condition来搭配实现。
下面贴上这3个包的简单示例代码。

1.ReetrantLock

A good article on what is ReentrantLock

ReetrantLock相比于synchronized一个很明显的机制差异就是ReetrantLock 可以中断一个正在等候获得锁的线程,也可以通过投票得到锁,如果不想等下去,那么就是它了。
ReetrantLock简单示例代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ThreadDemo1 {
    /** * @param args */
    public static void main(String[] args) {
        final Output output = new Output();
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    output.print("Hello Beauty");
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    output.print("HelloWorld");
                }
            }
        }).start();
    }
}

class Output {
    Lock lock = new ReentrantLock();

    public void print(String name) {
        lock.lock();
        try {
            for (int i = 0; i < name.length(); i++) {
                System.out.print(name.charAt(i));
            }
            System.out.println();
        } finally {
            lock.unlock();// 请记住一定要在finally块里释放锁,ReentrantLock不会自动释放锁,不然程序抛出异常
        }
    }
}
  1. ReentrantReadWriteLockReentrantReadWriteLock是针对于共享数据的读写优化,多线程在读操作是不会产生互斥的,而在写操作时才有互斥,在大数据量的 同时读写操作时,会效率很多。
    ReentrantReadWriteLock简单示例代码如下:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import java.util.Random;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ThreadDemo2 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        final Queue queue = new Queue();
        new Thread(new Runnable() {

            @Override
            public void run() {
                while(true){
                    queue.getData();
                }
            }
        }).start();
        new Thread(new Runnable() {

            @Override
            public void run() {
                while(true){
                    queue.putData();
                }
            }
        }).start();
    }
}
class Queue{
    private Object data;//被共享
    ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
    public void getData(){
        rwl.readLock().lock();//不互斥,大家都可以访问
        try{
            System.out.println(Thread.currentThread().getName()+"准备读取数据");
            try {
                Thread.sleep(new Random().nextInt(1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"获得数据"+this.data);
        }finally{
            rwl.readLock().unlock();
        }

    }
    public void putData(){
        rwl.writeLock().lock();//写锁互斥,一个线程进来,读写的其它线程都不能访问
        try{
            System.out.println(Thread.currentThread().getName()+"准备存入数据");
            this.data = new Random().nextInt(500);
            try {
                Thread.sleep(4000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"存入数据"+this.data);
        }finally{
            rwl.writeLock().unlock();//记住此操作不可省略
        }
    }
}
  1. Condition

Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。线程之间除了同步互斥,还要考虑通信。在Java5之前我们的通信方式为:wait 和 notify。那么Condition的优势是支持多路等待,就是我们可以定义多个Condition,每个condition控制线程的一条执行通路。传统方式只能是一路等待。
ReetrantLock简单示例代码如下:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ThreadDemo3 {
    public static void main(String[] args) {
        final Bus bus = new Bus();
        new Thread(new Runnable() {

            @Override
            public void run() {
                for(int i = 1; i <= 50;i++){
                    bus.sub1();
                }
            }
        }).start();
       new Thread(new Runnable() {

            @Override
            public void run() {
                for(int i = 1; i <= 50;i++){
                    bus.sub2();
                }
            }
        }).start();
       new Thread(new Runnable() {

            @Override
            public void run() {
                for(int i = 1; i <= 50;i++){
                    bus.sub3();
                }
            }
        }).start();
    }

}
class Bus{
    int flag = 1;
    Lock lock = new ReentrantLock();
    Condition condition1 = lock.newCondition();
    Condition condition2 = lock.newCondition();
    Condition condition3 = lock.newCondition();
    public void sub1(){
        lock.lock();
        try{
            while(flag!=1){
                try {
                    //this.wait();
                    condition1.await();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            for(int i = 1; i <= 10; i++){
                System.out.println("老大循环"+i+"次");
            }
            //this.notify();
            condition2.signal();
            flag = 2;
        }finally{
            lock.unlock();
        }
    }
    public void sub2(){
        lock.lock();
        try{
            while(flag!=2){
                try {
                    //this.wait();
                    condition2.await();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            for(int i = 1; i <= 20;i++){
                System.out.println("老二"+i+"次");
            }
        //  this.notify();
            condition3.signal();
            flag = 3;
        }finally{
            lock.unlock();
        }
    }
    public void sub3(){
        lock.lock();
        try{
            while(flag!=3){
                try {
                    //this.wait();
                    condition3.await();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            for(int i = 1; i <= 30;i++){
                System.out.println("老三"+i+"次");
            }
        //  this.notify();
            condition1.signal();
            flag = 1;
        }finally{
            lock.unlock();
        }
    }
}

Condition await will release the lock and wait for the signal.
Once signaled, in all cases, before this method can return, the current thread must ‘RE-acquire‘ the lock associated with this condition.

FROM HERE

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s