多线程(4)- Lock和Condition

ReentrantLock锁:

Java.util.concurrent.lock 中的Lock 框架是锁定的一个抽象,它允许把锁定的实现作为 Java 类,而不是作为语言的特性来实现。这就为Lock 的多种实现留下了空间,各种实现可能有不同的调度算法、性能特性或者锁定语义。

ReentrantLock 类实现了Lock ,它拥有与synchronized 相同的并发性和内存语义,但是添加了类似锁投票、定时锁等候和可中断锁等候的一些特性。此外,它还提供了在激烈争用情况下更佳的性能。(换句话说,当许多线程都想访问共享资源时,JVM 可以花更少的时候来调度线程,把更多时间用在执行线程上。)

区别:
需要注意的是,用sychronized修饰的方法或者语句块在代码执行完之后锁自动释放,而是用Lock需要我们手动释放锁,所以为了保证锁最终被释放(发生异常情况),要把互斥区放在try内,释放锁放在finally内!

Condition:

Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。
Condition可以替代传统的线程间通信,用await()替换wait(),用signal()替换notify(),用signalAll()替换notifyAll()。
传统线程的通信方式,Condition都可以实现。
注意,Condition是被绑定到Lock上的,要创建一个Lock的Condition必须用newCondition()方法。
Condition的强大之处在于它可以为多个线程间建立不同的Condition

这里写图片描述
使用三种方法时注意要处理异常

参考:http://blog.youkuaiyun.com/vking_wang/article/details/9952063

生产者消费者问题:

上篇文章中使用synchronized和this.notifyall()解决了这个问题,但是唤醒的是全部线程,可能会产生唤醒本方的另一个线程,然后去判断,无疑这是一种不好的现象。使用condition可以建立多个Condition对象,有效地解决了这个问题。

import java.util.concurrent.locks.*;

class Test 
{
    public static void main(String[] args) 
    {
        Resource r = new Resource();

        Producer pro = new Producer(r);
        Consumer con = new Consumer(r);

        Thread t1 = new Thread(pro);
        Thread t2 = new Thread(pro);
        Thread t3 = new Thread(con);
        Thread t4 = new Thread(con);

        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}
class Resource
{
    private String name;
    private int count = 1;
    private boolean flag = false;
    /*创建锁对象,并创建该锁的两个Condition对象*/
    private Lock lock=new ReentrantLock();
    private Condition pro_condition=lock.newCondition();
    private Condition con_condition=lock.newCondition();
    public void set(String name)throws Exception
    {
        lock.lock();
        try{
            while(flag)
                pro_condition.await();
            this.name = name+"--"+count++;
            System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
            flag = true;
            con_condition.signal();//唤醒对方的线程
        }
        finally{
            lock.unlock();
        }
    }

    public void out()throws Exception
    {
        lock.lock();
        try{
            while(!flag)
                con_condition.await();
            System.out.println(Thread.currentThread().getName()+"...消费者......"+this.name);
            flag = false;
            pro_condition.signal();
        }
        finally{
            lock.unlock();
        }
    }
}

class Producer implements Runnable
{
    private Resource res;

    Producer(Resource res)
    {
        this.res = res;
    }
    public void run()
    {
        while(true)
        {
            try{
                res.set("+商品+");
            }
            catch(Exception e){
                e.printStackTrace();
            }
        }
    }
}

class Consumer implements Runnable
{
    private Resource res;

    Consumer(Resource res)
    {
        this.res = res;
    }
    public void run()
    {
        while(true)
        {
            try{
                res.out();
            }
            catch(Exception e){
                e.printStackTrace();
            }
        }
    }
}

这里是将await()和signal()方法的异常抛出,在其调用者的函数里用catch处理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值