JDK1.5新特性——Lock、Condition接

本文深入探讨了Java中Lock和Condition接口的应用,通过示例对比了它们与synchronized关键字的不同之处,尤其是在多生产者多消费者场景下的灵活性提升。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


        我们知道,多线程中往往会对同一资源数据进行操作,这就意味着需要同步处理。
        同步处理的过程:某线程拿到锁,持有锁,进行数据操作,释放锁。
        同步处理的原则:保证对数据操作的完整性。

        以往我们用synchronized修饰函数或定义synchronized语句块来实现同步处理的过程,我们只需要定义怎么处理数据就行了,而不考虑锁什么时候锁上、什么时候打开。同步函数的锁往往是本类对象的this引用或本类的字节码对象。

        而在JDK1.5中,提供了一种锁处理机制,即Lock、Condition接口。这里需要手动上锁、手动开锁。
        而且新特性更加的灵活。举个例子,在多生产多消费的线程中,我们用while循环来判断,用notifyAll()来唤醒所有的线程,那么不能只单单唤醒对方阵营中某一线程吗?而利用Lock、Condition是能实现的。

        这两个接口都是在java.util.concurrent.locks下的,所有使用时需要导包。

1 接口Lock

1.1 方法

1.1.1 void lock()

        获取锁。可以让别的线程无法执行已上锁的代码。

1.1.2 void unlock()

        释放锁。允许别的线程访问此代码。

1.1.3 ConditionnewCondition()

        返回绑定到此Lock实例的新Condition实例。

1.2 实现Lock接口的类

1.2.1 ReentrantLock

        一个可重入的互斥锁Lock,它具有与使用synchronized方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大。

        Locklock = newReentrantLock();//父类引用指向子类对象。

        Condition condition =lock.newCondition();

2 接口Condition

2.1 方法

2.1.1 void await() throws InterruptedException

        使当前线程进入阻塞(等待)状态。

2.1.2 void signal()

        唤醒一个等待线程。

2.1.3 void signalAll()

        唤醒所有等待线程。

3 使用方法

class Resource
{
	//公共资源属性
	boolean flag = true; //标记值
	final Lock lock = new ReentrantLock(); //生产一个锁(父类引用指向子类对象)
	final Condition condition = lock.newCondition();//用生成的锁Condition实例
	//同一个锁可以有n个不同的Condition实例,分别对不同的线程起作用哦
	void set(公共资源)
	{
		lock.lock();//加锁
		try
		{
			if(!flag)          //多线程 用while判断
				condition.await(); //满足条件,等待(等待前finally释放锁)
			//对公共资源的操作(写操作,生产)
			flag = false;
			condition.signal();//唤醒其他线程      //多线程 用signalAll()唤醒全部线程
		}
		catch(InterruptedException e)
		{//异常处理:1、try-catch处理 2、throws处理(如下)
		}
		finally
		{
			lock.unlock();//释放锁
		}
	}
	void get() throws InterruptedException //异常处理:抛给调用者处理
	{
		lock.lock();
		try
		{
			if(flag)
				condition.await();
			//对公共资源的操作(读操作,消费)
			flag = true;
			condition.signal();
		}
		finally
		{
			lock.unlock();
		}
	}
}

4 改写程序

4.1 改写单生产单消费的程序

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Goods
{
	String name;
	int id = 0;
	boolean flag = true;
	final Lock lock = new ReentrantLock();
	final Condition condition = lock.newCondition();
	void set(String name) throws InterruptedException
	{
		lock.lock();
		try
		{
			if(!flag)
				condition.await();
			this.name = name;
			id++;
			System.out.println(Thread.currentThread().getName()+"--商品--"+name+"--"+id);
			flag = false;
			condition.signal();
		}
		finally
		{
			lock.unlock();
		}
	}
	void get()
	{
		lock.lock();
		try
		{
			if(flag)
				condition.await();
			System.out.println(Thread.currentThread().getName()+"--商品--"+name+"--"+id);			flag = true;
			condition.signal();
		}
		catch(InterruptedException e)
		{
		}
		finally
		{
			lock.unlock();
		}
	}
}
class SetGoods implements Runnable
{
	private Goods goods;
	public SetGoods(Goods goods)
	{
		this.goods = goods;
	}
	public void run()
	{
		int n = 500;
		while(n-- > 0)
		{
			try
			{
				goods.set("汉堡");
			}
			catch(InterruptedException e)
			{
			}
		}
	}
}
class GetGoods implements Runnable
{
	private Goods goods;
	public GetGoods(Goods goods)
	{
		this.goods = goods;
	}
	public void run()
	{
		int n = 500;
		while(n-- > 0)
			goods.get();
	}
}
public class Main
{
	public static void main(String[] args)
	{
		Goods goods = new Goods();
		new Thread(new SetGoods(goods), "A生产").start();
		new Thread(new GetGoods(goods), "C消费").start();
	}
}

4.2 改写多生产多消费的程序

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Goods
{
	String name;
	int id = 0;
	boolean flag = true;
	final Lock lock = new ReentrantLock();
	final Condition condition = lock.newCondition();
	void set(String name) throws InterruptedException
	{
		lock.lock();
		try
		{
			while(!flag)
				condition.await();
			this.name = name;
			id++;
			System.out.println(Thread.currentThread().getName()+"--商品--"+name+"--"+id);
			flag = false;
			condition.signalAll();
		}
		finally
		{
			lock.unlock();
		}
	}
	void get()
	{
		lock.lock();
		try
		{
			while(flag)
				condition.await();
			System.out.println(Thread.currentThread().getName()+"--商品--"+name+"--"+id);			flag = true;
			condition.signalAll();
		}
		catch(InterruptedException e)
		{
		}
		finally
		{
			lock.unlock();
		}
	}
}
class SetGoods implements Runnable
{
	private Goods goods;
	public SetGoods(Goods goods)
	{
		this.goods = goods;
	}
	public void run()
	{
		int n = 500;
		while(n-- > 0)
		{
			try
			{
				goods.set("汉堡");
			}
			catch(InterruptedException e) {}
		}
	}
}
class GetGoods implements Runnable
{
	private Goods goods;
	public GetGoods(Goods goods)
	{
		this.goods = goods;
	}
	public void run()
	{
		int n = 500;
		while(n-- > 0)
			goods.get();
	}
}
public class Main
{
	public static void main(String[] args)
	{
		Goods goods = new Goods();
		new Thread(new SetGoods(goods), "A生产").start();
		new Thread(new SetGoods(goods), "B生产").start();
		new Thread(new GetGoods(goods), "C消费").start();
		new Thread(new GetGoods(goods), "D消费").start();
	}
}

新特性更加的灵活。举个例子,在多生产多消费的线程中,我们用while循环来判断,用notifyAll()来唤醒所有的线程,那么不能只单单唤醒对方阵营中某一线程吗?而利用Lock、Condition是能实现的。

        看4.2改写多生产多消费的程序,也没有体现出比synchronized更加灵活的地方来,依旧是唤醒所有的程序啊?

5 使用方法升级版

class Resource
{
	//公共资源属性
	boolean flag = true;
	final Lock lock = new ReentrantLock();
	final Condition conditionProduce = lock.newCondition(); //lock产生两个Condition对象
	final Condition conditionConsume = lock.newCondition();
	void set(公共资源)
	{
		lock.lock();
		try
		{
			while(!flag)
				conditionProduce.await();//是当前线程等待
			//数据操作
			flag = false;
			conditionConsume.signal();//将对方阵营中的一个线程唤醒
		}
		catch(Exception e) {}
		finally   //必执行代码块
		{
			lock.unlock();
		}
	}
	void get()
	{
		lock.lock();
		try
		{
			while(!flag)
				conditionConsume.await();//是当前线程等待
			//数据操作
			flag = false;
			conditionProduce.signal();//将对方阵营中的一个线程唤醒
		}
		catch(Exception e) {}
		finally   //必执行代码块
		{
			lock.unlock();
		}
	}
}

一个lock实例产生两个Condition对象,分别对不同的线程加以标记,从而进行不同的操作。

6 你会再次改写多生产多消费的例子吗?








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值