synchronized和ReentrantLock实现消费者生产者问题

并发执行和并行执行的区别:并行执行是指两个或多个事件在同一时刻发生,而并发执行是指两个或多个事情在同一时间间隔内发生。并发执行在宏观层面上看,事情之间是同时发生的。比如说在2秒的时间内发生的两件事情,在历史的角度上可以看作是“同时发生”的。

在Java中,多个线程对临界区资源操作时,需要保持程序的可再现性,或者说内存可见性。不管哪个线程操作了临界资源,操作的结果都应该对下一个操作该资源的线程可见。我们需要通过线程间的同步机制来实现程序的可再现性。在Java中有两种方法实现:1.使用synchronized关键字  2.使用ReentrantLock对象

对于synchronized可以使用同步方法或者同步代码块的方式。使用这种方法,我们需要给定一个锁对象。

public class Resource2 {
	// count为临界资源
	private int count;
	//flag标记是否是应该生产还是消费
	private boolean flag = false;

	public int getCount() {
		return count;
	}

	public void setCount(int count) {
		this.count = count;
	}

	public void productor() {
		synchronized (this) {

			while (!flag) {
				try {
					wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}

			count++;
			System.out.println(Thread.currentThread().getName() + "。。。。。生产。。。。"
					+ count);
			flag = false;
			notifyAll();
		}
	}

	public void customer() {

		synchronized (this) {
			while (flag) {
				try {
					wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}

			System.out.println(Thread.currentThread().getName()+ "。。。。。。。。。。。消费。。。。。。。。" + count);
			flag = true;
			notifyAll();
		}

	}
}

这里使用了同步代码块,注意的是wait()方法和notifyAll()方法是锁调用的。因为锁的状态由系统在维护,所以锁被释放的时候,只有它自己知道。这里使用的是对象本身。当然啦,可以直接在方法上加synchronized,这里默认的锁仍然是对象本身,但是当方法是静态的时候则是对象的字节码对象,即 类名.Class。notify方法是从线程池中唤醒其中一个线程,notifyAll很明显是把所有的线程都唤醒。很明显这里要用notifyAll,如果使用notify则可能会出现死锁的状况。假如前一个wait的是生产者,而notify唤醒的签好也是生产者线程,那么生产的东西无法被消费,所以会一直等待....

我们来介绍第二种方式,对于ReentrantLock,你需要自己创建锁,上锁然后释放锁。这会在某些情况下带给我们很好的处理,我们可以自己进行出错时处理,而不像synchronized,由系统维护者,出错时只能由系统处理,一般是抛出异常或错误。而且ReentrantLock还提供了trylock(int timeout, Type),通过这个方法,你可以在线程无法获得锁的时候去执行其它的任务,而不是像synchronized那样,获取不到就会一直等待着。这个方法该怎么唤醒其它线程呢,是不是跟synchronized那样使用锁的wait()和notify()或者notifyAll()呢?当然不是啦。ReentrantLock只是提供了锁,而锁的释放或者上锁是的状态是要通过ReentrantLock的内部类Condition来监视的。说白了Condition就是锁的一个监视器,同一把锁可以定义多组监视器,这样在分工的时候就不需要唤醒所有的线程,而是唤醒所需职能的线程。对于生产者消费者我们可以定义两组监视器,分别监听这两种分工线程。当然啦,锁由你创建并操作,那么你操作完了应该释放它,不然会出大问题。为了保证锁的释放,肯定在finally中进行啦。

public class Resource{
	//count为临界资源
	private int count;
	
	private boolean flag = true;
	
	//锁
	private ReentrantLock lock;
	//两组监视器
	private Condition proCondition;
	private Condition cusCondition;
	
	public Resource(){
		lock = new ReentrantLock();
		proCondition = lock.newCondition();
		cusCondition = lock.newCondition();
	}
	public Resource(int count){
		this.count = count;
		lock = new ReentrantLock();
		proCondition = lock.newCondition();
		cusCondition = lock.newCondition();
	}
	
	public int getCount() {
		return count;
	}
	public void setCount(int count) {
		this.count = count;
	}
	
	
	public  void productor(){
			lock.lock();
			try {
				while(!flag){
					try {
						proCondition.await();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				
				count++;
				System.out.println(Thread.currentThread().getName()+"。。。。。生产。。。。"+count);
				flag = false;
				cusCondition.signal();
			}finally{
				lock.unlock();
			}
			
		
	}
	
	public void customer(){
		
		lock.lock();
		try {
			while(flag){
				try {
					cusCondition.await();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			
			System.out.println(Thread.currentThread().getName()+"。。。。。。。。。。。消费。。。。。。。。"+count);
			flag = true;
			proCondition.signal();
		}finally{
			lock.unlock();
		}
			
	}
}

最后定义两个任务

public class MainActivity {
	
	public static void main(String[] args) {
		Resource2 resource2 = new Resource2();
		ResourceTask proTask = new ResourceTask(resource2);
		HandlerTask cusTask = new HandlerTask(resource2);
		
		Thread proThread1 = new Thread(proTask);
		Thread proThread2 = new Thread(proTask);

		Thread cusThread3 = new Thread(cusTask);
		Thread cusThread4 = new Thread(cusTask);
		
		proThread1.start();
		proThread2.start();
		
		cusThread3.start();
		cusThread4.start();
	}
	
	
	static class ResourceTask implements Runnable{
		private Resource2 resource;
		
		public ResourceTask(Resource2 resource){
			this.resource = resource;
		}
		
		@Override
		public void run() {
			while(true)
			resource.productor();
		}
		
	}
	
	static class HandlerTask implements Runnable{
		private Resource2 resource;
		
		public HandlerTask(Resource2 resource){
			
			this.resource = resource;
		}
		
		@Override
		public void run() {
			while(true)
			resource.customer();
		}
		
	}
}








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值