这篇主要讲解,JDK1.5以后,对多线程技术的改进。那么,为什么要对之前的技术进行改进呢,在上篇中的多生产者,多消费者例子中,当有一个线程在执行时,其他的线程在申请对锁的拥有权是,会不断的进行判断,这样会降低降低程序的性能。为此,JDK 1.5 以后,对多线程技术做了改进。
JDK1.5后出现的新的接口和类:Lock:比同步函数和同步代码块要好一些。同步函数还是同步代码块所做的都是隐式的锁操作。并且,同步函数或者同步代码块使用的锁和监视器是同一个。
Lock接口:是将锁进行单独对象的封装。而且提供了对锁对象很多功能。 比如:lock()获取锁,unlock()释放锁。 Lock对锁的操作都是显示操作。所以它的出现要比同步函数或者同步代码块明确的多,更符合面向对象思想。
简单一句话:Lock接口的出现替代同步。
下面将上述的生产者消费者 代码,进行 Lock 改写:
class Resource
{
private String name;
private int count = 1;
private boolean flag;
//创建一个锁对象。
private final Lock lock = new ReentrantLock();
//获取一个该锁上的监视器。
private Condition con = lock.newCondition();
public void set(String name)//
{
//获取锁。
lock.lock();
try
{
while(flag)
try{con.await();}catch(InterruptedException e){}
this.name = name + count;
count++;
System.out.println(Thread.currentThread().getName()+".....生产者......"+this.name);
flag = true;
con.signalAll();
}
finally
{
//释放锁。
lock.unlock();
}
}
public void get()//
{
lock.lock();
try
{
while(!flag)
try{con.await();}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+".........消费者......"+this.name);
flag = false;
con.signalAll();
}
finally
{
lock.unlock();
}
}
}
这样,对锁的操作显而易见。清晰的很。
原来在同步中,锁和监视器是同一个对象。现在,升级后,锁是一个单独的对象。而且将监视器的方法也单独封装到了一个对象中。这个对象就是升级后Condition.
升级后,都进行了单独的封装。锁被封装成了Lock对象。监视器方法都被封装到了Condition对象(监视器对象)中。 说白了,Lock替代了同步,Condition替代了Object中的监视器方法。
Condition中提供了监视器的方法:awati().signal(),signalAll();
那么,该 如何让锁和监视器产生联系呢?
直接通过Lock接口中的newCondition()方法就可以获取到能绑定到该Lock对象的上的监视器对象Condition。
之前,我们为了解决,1,本方唤醒了本方。2,被唤醒的本方没有判断标记。这两个问题时,将if 改为 while , 并且用了 notifyAll() ,这种解决方案效率低,因为还会唤醒本方。
有了新特性Lock,Condition。就可以解决这个问题了。之前是有两个锁嵌套,容易死锁,现在方案是只有锁,但是锁上可以加入多个监视器 :一个监视生产者,一个监视消费者。
改写后的代码为:
class Resource
{
private String name;
private int count = 1;
private boolean flag;
//创建一个锁对象。
private final Lock lock = new ReentrantLock();
//创建一个生产者的监视器。
private Condition producer_con = lock.newCondition();
//创建一个消费者监视器。
private Condition consumer_con = lock.newCondition();
public void set(String name)//
{
//获取锁。
lock.lock();
try
{
while(flag)
try{producer_con.await();}catch(InterruptedException e){}
this.name = name + count;
count++;
System.out.println(Thread.currentThread().getName()+".....生产者......"+this.name);
flag = true;
consumer_con.signal();
}
finally
{
//释放锁。
lock.unlock();
}
}
public void get()//
{
lock.lock();
try
{
while(!flag)
try{consumer_con.await();}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+".........消费者......"+this.name);
flag = false;
producer_con.signal();
}
finally
{
lock.unlock();
}
}
}