Synchronized和ReenTrantLock都可以实现同步队列,ReenTrantLock可以实现更多的功能,比如条件通知,自己实现了一个生产者消费者模型。
首先简单讲一下它们的区别:
- 两者都是可重入锁,
- Synchronized依赖于JVM ,而ReenTrantLock依赖于API
- ReenTrantLock相对于Synchronized有更多高级功能,比如可以实现公平锁,和条件通知(下面的例子),通过condition接口绑定条件,从而实现定向通知。
下面是代码,加上注释很容易看懂:
package offer;
import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
//ReentrantLock实现条件通知,条件满足时,通知相应线程
//以生产者消费者为例
public class ReentrantLockDemo<E> {
private final LinkedList<E> list = new LinkedList<E>();
private final int MAX = 10;
private int count = 0;
private Lock lock = new ReentrantLock();
private Condition producer = lock.newCondition();
private Condition consumer = lock.newCondition();
public int getCount(){
return count;
}
public void put(E e){
lock.lock();
try{
while(list.size()==MAX){
System.out.println(Thread.currentThread().getName()+"等待中。。");
//借助条件进入等待队列
producer.await();
}
System.out.println(Thread.currentThread().getName()+"put。。");
list.add(e);
count++;
//唤醒所有消费者
consumer.signalAll();
}catch (InterruptedException e1) {
e1.printStackTrace();
}finally {
//lock锁一定要手动释放
lock.unlock();
}
}
public E get(){
E e = null;
lock.lock();
try{
while(list.size()==0){
System.out.println(Thread.currentThread().getName()+"等待中。。");
//进入等待队列
consumer.await();
}
System.out.println(Thread.currentThread().getName()+"get。。");
e = list.removeFirst();
count--;
//唤醒所有消费者
producer.signalAll();
}catch (InterruptedException e2) {
e2.printStackTrace();
}finally {
//lock锁一定要手动释放
lock.unlock();
}
return e;
}
public static void main(String[] args){
final ReentrantLockDemo<String> c = new ReentrantLockDemo<>();
//创建10个消费者线程
for(int i=0;i<10;i++){
new Thread(new Runnable() {
@Override
public void run() {
for(int j=0;j<5;j++){
System.out.println(c.get());
}
}
},"consumr"+i).start();
}
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for(int i=0;i<2;i++){
new Thread(new Runnable() {
@Override
public void run() {
for(int j=0;j<20;j++){
c.put("container value" + j);
}
}
},"producer"+i).start();
}
}
}