加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

Java并发之读写锁Lock和条件阻塞Condition的应用

(2011-12-02 08:44:29)
标签:

java

5

并发

读写锁

lock

条件

阻塞

condition

应用

it

分类: 编程语言

Java 5中提供了另一种实现线程同步或互斥的机制,即使用LockCondition

Lock比传统线程模型中的synchronized方式更加面向对象,也提供了更多可选择的锁机制。与生活中的锁类似,锁本身也是一个对象。两个线程执行的代码片段要实现同步互斥的效果,它们必须使用同一个Lock对象。锁是上在代表要操作的资源的类的内部方法中,而不是线程代码中。

 

Lock使用示例:

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

 

// An example of using Lock.

public class LockTest {

 

public static void main(String[] args) {

new LockTest().init();

}

 

private void init(){

final Outputer outputer new Outputer();

new Thread(new Runnable(){

@Override

public void run() {

while(true){

try {

Thread.sleep(10);

catch (InterruptedException e) {

e.printStackTrace();

}

outputer.output("aaaaaaaaaaa");

}

 

}

}).start();

 

new Thread(new Runnable(){

@Override

public void run() {

while(true){

try {

Thread.sleep(10);

catch (InterruptedException e) {

e.printStackTrace();

}

outputer.output("bbbbbbbbbbb");

}

 

}

}).start();

 

}

 

static class Outputer{

private Lock lock new ReentrantLock();

public void output(String name){

int len name.length();

lock.lock();

try{

for(int i=0;i<len;i++){

System.out.print(name.charAt(i));

}

System.out.println();

}finally{

lock.unlock();

}

}

}

}

 

 

读写锁:分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥,写锁与写锁互斥,这是由JVM控制的,我们只需要上好相应的锁即可。如果代码只读数据,可以很多人同时读,但不能同时写,那就上读锁;如果代码修改数据,只能有一个人在写,并不能同时读取,那就上写销锁。总之,读的时候上读锁,写的时候上写锁。

Java读写锁示例:

 

import java.util.Random;

import java.util.concurrent.locks.ReadWriteLock;

import java.util.concurrent.locks.ReentrantReadWriteLock;

 

public class ReadWriteLockTest {

    public static void main(String[] args) {

        final MyQueue queue new MyQueue();

        for (int 0; 3; i++) {

            new Thread() {

                public void run() {

                    while (true{

                        queue.get();

                    }

                }

 

            }.start();

 

            new Thread() {

                public void run() {

                    while (true{

                        queue.put(new Random().nextInt(10000));

                    }

                }

 

            }.start();

        }

 

    }

}

 

class MyQueue {

    // 共享数据,只能有一个线程能写该数据,但可以有多个线程同时读该数据。

    private Object data null

    ReadWriteLock  rwl  new ReentrantReadWriteLock();

 

    public void get() {

        rwl.readLock().lock();

        try {

            System.out.println(Thread.currentThread().getName()

                    be ready to read data!");

            Thread.sleep((long(Math.random() 1000));

            System.out.println(Thread.currentThread().getName()

                    "have read data :" data);

        catch (InterruptedException e) {

            e.printStackTrace();

        finally {

            rwl.readLock().unlock();

        }

    }

 

    public void put(Object data) {

 

        rwl.writeLock().lock();

        try {

            System.out.println(Thread.currentThread().getName()

                    be ready to write data!");

            Thread.sleep((long(Math.random() 1000));

            this.data data;

            System.out.println(Thread.currentThread().getName()

                    have write data: " data);

        catch (InterruptedException e) {

            e.printStackTrace();

        finally {

            rwl.writeLock().unlock();

        }

    }

    

}

 

使用读写锁实现缓存机制:

 

import java.util.HashMap;

import java.util.Map;

import java.util.concurrent.locks.ReadWriteLock;

import java.util.concurrent.locks.ReentrantReadWriteLock;

 

// Using ReadWriteLock to implement cache.

public class CacheDemo {

 

    private Map<String, Object> cache new HashMap<String, Object>();

    private ReadWriteLock       rwl   new ReentrantReadWriteLock();

 

    public static void main(String[] args) {

        CacheDemo cache new CacheDemo();

        Object obj cache.getData("");

        System.out.println(obj.toString());

    }

 

    // Get the value from DB if the value does not exist,and then return it.

    public Object getData(String key) {

        rwl.readLock().lock();

        Object value null;

        try {

            value cache.get(key);

            if (value == null{

                // Must release read lock before acquiring write lock

                rwl.readLock().unlock();

                rwl.writeLock().lock();

                try {

                    // Recheck state because another thread might have acquired

                    // write lock and changed state before we did.

                    if (value == null{

                        // Here may access Database.

                        // ...

                        value "Data";

                    }

                finally {

                    rwl.writeLock().unlock();

                }

                rwl.readLock().lock();

            }

        finally {

            rwl.readLock().unlock();

        }

        return value;

    }

}

 

 

Condition的功能类似在传统线程技术中的Object.waitObject.notity的功能。在等待Condition时,允许发生“虚假唤醒”,这通常作为对基础平台语义的让步。对于大多数应用程序,这带来的实际影响很小,因为Condition应该总是在一个循环中被等待,并测试正被等待的状态声明。某个实现可以随意移除可能的虚假唤醒,但建议应用程序员总是假定这些虚假唤醒可能发生,因此总是在一个循环中等待。

一个锁内部可以有多个Condition,即有多路等待和通知,可以参看Jdk1.5提供的LockCondition实现的可阻塞队列的应用案例。在传统的线程机制中一个监视器对象上只能有一路等待和通知,要想实现多路等待和通知,必须嵌套使用多个同步监视器对象。

JDK文档中提供了一个很不错的示例(http://docs.oracle.com/javase/6/docs/api/ ),用Condition实现一个阻塞队列,代码如下:

 

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

 

public class BoundedBuffer {

    final Lock      lock     new ReentrantLock();

    final Condition notFull  lock.newCondition();

    final Condition notEmpty lock.newCondition();

 

    final Object[]  items    new Object[100];

    int             putptrtakeptrcount;

 

    public void put(Object x) throws InterruptedException {

        lock.lock();

        try {

            while (count == items.length)

                notFull.await();

            items[putptrx;

            if (++putptr == items.length)

                putptr 0;

            ++count;

            notEmpty.signal();

        finally {

            lock.unlock();

        }

    }

 

    public Object take() throws InterruptedException {

        lock.lock();

        try {

            while (count == 0)

                notEmpty.await();

            Object items[takeptr];

            if (++takeptr == items.length)

                takeptr 0;

            --count;

            notFull.signal();

            return x;

        finally {

            lock.unlock();

        }

    }

}

 

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有