在Java1.5以前的版本中,因为监视器是来自于Object,为了线程的互斥访问,用的synchronized方法或者模块
- 在synchronized中,“锁”的操作是隐式的,而且每一个锁里只能有一组wait-notify或是wait-notifyAll方法,这样的弊端在于
等待和唤醒的缓冲线程里不仅包括了生产者也包括了消费者,这样就不能指定唤醒进程,要么唤醒了全部进程,影响了效率,要么休眠了所有进程,发生死锁
Java从1.5版本开始支持新的”锁“,体现的面向对象的特点,将锁封装起来
- Lock实例可以通过Condition挂载多个监视器
Condition c1 = lock.newCondition();
Condition c2 = lock.newCondition();
Condition中的await(),signal() ,signalAll() 来替换对应Object对象锁的方法
这样就可以实现一个锁,而指定唤醒对方进程,避免死锁,提高执行效率
java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。
java.util.concurrent.locks
接口 Lock
所有已知实现类:
ReentrantLock,ReentrantReadWriteLock.ReadLock, ReentrantReadWriteLock.WriteLock
- 关于ReentrantLock
一个可重入的互斥锁 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大。
其实就是synchronized的隐形锁换成了Lock中的显示锁及显示操作
void method(){
{
synchronized (obj)//对象锁
{
//code...
}
}
改了形式
Lock lock = new ReentrantLock();//
void method()
{
try
{
lock.lock();//显示获取锁
code...throw Exception();//因为可能发生中断异常,所以把管闭锁的动作放到finally中
}
finally
{
lock.unlock();
}
eg:
mport java.util.concurrent.locks.*;
class Resource
{
String name;
private int count = 1;
String id ;
private boolean flag = false;//初始默认没有产品
//创建锁
Lock lock = new ReentrantLock();
//通过已有的锁创建两个监视,分别监视生产者和消费者
Condition cp = lock.newCondition();//生产者监视器
Condition cc = lock.newCondition();//消费者监视器
public void producer(String name)
{
try
{
lock.lock();
while(flag)
try{cp.await();} catch (InterruptedException ex){}//生产者等待
this.name = name;
id = name + count++;
System.out.println(Thread.currentThread().getName()+"--->生产:"+id);
flag = true;
cc.signal();//唤醒消费者
}
finally
{
lock.unlock();
}
}
public void consumer()
{
try
{
lock.lock();
while(!flag)
try{cc.await();} catch (InterruptedException ex){}//消费者等待
System.out.println(Thread.currentThread().getName()+"--------->消费"+id);
flag = false;
cp.signal();//唤醒生产者
}
finally
{
lock.unlock();
}
}
}
class Producer implements Runnable
{
Resource r;
Producer(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
r.producer("包子");
}
}
}
class Consumer implements Runnable
{
Resource r;
Consumer(Resource r)
{
this.r = r;
}
public void run()
{
while (true)
{
r.consumer();
}
}
}
class ThreadPC3
{
public static void main(String[] args)
{
//创建资源
Resource r = new Resource();
//创建线程任务
Producer p0 = new Producer(r);
Producer p1 = new Producer(r);
Consumer c0 = new Consumer(r);
Consumer c1 = new Consumer(r);
//创建线程
Thread tp0 = new Thread(p0);
Thread tp1 = new Thread(p1);
Thread tc0 = new Thread(c0);
Thread tc1 = new Thread(c1);
//开启线程
tp0.start();
tp1.start();
tc0.start();
tc1.start();
}
}
这个是API中的例子:
这个不用自己实现,已经封装的
class BoundedBuffer {
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final Object[] items = new Object[100];
int putptr, takeptr, count;
public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length)
notFull.await();
items[putptr] = x;
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 x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;
notFull.signal();
return x;
} finally {
lock.unlock();
}
}
}