JDK1.5中提供了多线程升级解决方案,将synchronized替换为了显示的Lock操作。将Object中的wait、notify、notifyAll替换为了condition对象(该对象可以通过Lock锁进行获取)。
有关Lock接口以及condition对象的详细介绍请查找官方API,这里不做详细介绍,我只是想通过两个例子来对比一下synchronized和Lock。
使用synchronized的生产者和消费者关系:
class Resource {
// 产品名称
private String name;
// 计数器
private int count = 0;
// 标志位,标志 生产或消费
private boolean flag = false;
// 生产活动
public synchronized void set(String name) {
// 如果flag为true,则说明已经生产还未消费,使线程进入等待状态
// 循环判断,线程被唤醒后也进行判断确保产品已经消费
while (flag)
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.name = name + "---" + ++count;
System.out.println(Thread.currentThread().getName() + "...生产者..."
+ this.name);
// 产品已生产,flag置为true
flag = true;
// 唤醒所有线程
this.notifyAll();
}
// 消费活动
public synchronized void out() {
// 如果flag为false,则说明还已经消费还未生产,使线程进入等待状态
// 循环判断,线程被唤醒后也进行判断确保产品已经生产
while (!flag)
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "...消费者..."
+ this.name);
// 产品已消费,flag置为false
flag = false;
// 唤醒所有线程
this.notifyAll();
}
}
// 生产者
class Producer implements Runnable {
private Resource res;
public Producer(Resource res) {
this.res = res;
}
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
res.set("++商品++");
}
}
}
// 消费者
class Consumer implements Runnable {
private Resource res;
public Consumer(Resource res) {
this.res = res;
}
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
res.out();
}
}
}
public class ProducerConsumer {
public static void main(String[] args) {
// TODO Auto-generated method stub
Resource resource = new Resource();
Producer producer = new Producer(resource);
Consumer consumer = new Consumer(resource);
Thread t1 = new Thread(producer);
Thread t2 = new Thread(producer);
Thread t3 = new Thread(consumer);
Thread t4 = new Thread(consumer);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
使用Lock锁的生产者和消费者关系:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Resource {
// 产品名称
private String name;
// 计数器
private int count;
// 标志位,标志 生产或消费
private boolean flag = false;
// 创建Lock锁
private Lock lock = new ReentrantLock();
// 创建condition对象
private Condition condition_pro = lock.newCondition();
private Condition condition_Con = lock.newCondition();
// 生产活动
public void set(String name) {
// 上锁
lock.lock();
try {
// 如果flag为true,则说明已经生产还未消费,使线程进入等待状态
// 循环判断,线程被唤醒后也进行判断确保产品已经消费
while (flag)
// 线程休眠
condition_pro.await();
this.name = name + "---" + ++count;
System.out.println(Thread.currentThread().getName() + "...生产者..."
+ this.name);
// 产品已生产,flag置为true
flag = true;
// 唤醒所有线程
condition_Con.signalAll();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
// 解锁,该动作一定要执行
lock.unlock();
}
}
// 消费活动
public void out() {
// 上锁
lock.lock();
try {
// 如果flag为false,则说明还已经消费还未生产,使线程进入等待状态
// 循环判断,线程被唤醒后也进行判断确保产品已经生产
while (!flag)
// 线程休眠
condition_Con.await();
System.out.println(Thread.currentThread().getName() + "...消费者..."
+ this.name);
// 产品已消费,flag置为false
flag = false;
// 唤醒所有线程
condition_pro.signalAll();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
// 解锁,该动作一定要执行
lock.unlock();
}
}
}
// 生产者
class Producer implements Runnable {
private Resource res;
public Producer(Resource res) {
this.res = res;
}
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
res.set("++商品++");
}
}
}
// 消费者
class Consumer implements Runnable {
private Resource res;
public Consumer(Resource res) {
this.res = res;
}
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
res.out();
}
}
}
public class ProducerConsumer {
public static void main(String[] args) {
// TODO Auto-generated method stub
Resource resource = new Resource();
Producer producer = new Producer(resource);
Consumer consumer = new Consumer(resource);
Thread t1 = new Thread(producer);
Thread t2 = new Thread(producer);
Thread t3 = new Thread(consumer);
Thread t4 = new Thread(consumer);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
通过对比可以看出,一个Lock锁可以对应多个condition,解决了锁嵌套时出现的死锁现象。