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处理