`
zhangyeny
  • 浏览: 31632 次
  • 性别: Icon_minigender_1
  • 来自: 厦门
社区版块
存档分类
最新评论

java并发中Lock和Synchronized的异同

 
阅读更多
java中可以使用Lock和Synchronized的可以实现对某个共享资源的同步,同时也可以实现对某些过程的原子性操作
Lock可以使用Condition进行线程之间的调度
Synchronized则使用Object对象本身的notify, wait, notityAll调度机制
这两种调度机制有什么异同呢?
Condition是Java5以后出现的机制,它有更好的灵活性,而且在一个对象里面可以有多个Condition(即对象监视器),则线程可以注册在不同的Condition,从而可以有选择性的调度线程,更加灵活。
Synchronized就相当于整个对象只有一个单一的Condition(即该对象本身)所有的线程都注册在它身上,线程调度的时候之后调度所有得注册线程,没有选择权,会出现相当大的问题
下面是一个场景,针对这个场景提出两种解决方案。
一个中转站,可以接纳货物,然后发出货物,这是需要建一个仓库,相当于一个缓冲区,当仓库满的时候,不能接货,仓库空的时候,不能发货。
第一种,用一个Condition去解决,有可能会出问题

package com.zxx;

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 单个Condition去控制一个缓冲区,多线程对缓冲区做读写操作,要保证缓冲区满的时侯不会
 * 被写,空的时候不会被读;单个Condition控制会出错误: 当缓冲区还有一个位置时,多个写线程
 * 同时访问,则只有一个写线程可以对其进行写操作,操作完之后,唤醒在这个condition上等待的
 * 其他几个写线程,如果判断用IF语句的话就会出现继续向缓冲区添加。
 * @author Administrator
 *
 */
public class ConditionError {
	Lock lock = new ReentrantLock();
	Condition condition = lock.newCondition();
	String[] container = new String[10];
	int index = 0;
	public static void main(String[] args) {
		ConditionError conditionError = new ConditionError();
		conditionError.test();
	}
	
	public void test(){
		ExecutorService threadPool = Executors.newCachedThreadPool();
		for(int i = 0; i < 14; i++){//先用14个线程去写,则有4个线程会被阻塞
			threadPool.execute(new Runnable(){

				@Override
				public void run() {
					put();
				}
				
			});
		}
		
		Executors.newSingleThreadExecutor().execute(new Runnable(){//用一个线程去取,则会通知4个阻塞的写线程工作,此时
																//会有一个线程向缓冲区写,写完后去通知在这个condition上等待
																//的取线程,这是它的本意,但是它唤醒了写线程,因为只有一个condition
																//不能有选择的唤醒写取线程,此时就需要有多个Condition
			@Override
			public void run() {
				try {
					Thread.sleep(10000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				get();
			}
			
		});
	}
	
	/**
	 * 向缓冲去写数据
	 */
	public void put(){
		lock.lock();
		try{
			System.out.println(Thread.currentThread().getName() + "当前位置:" + index + "-----------------------------");
			while(index == 10){
				try {
					System.out.println(Thread.currentThread().getName() + "处于阻塞状态!");
					condition.await();
//					index = 0;
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			container[index] = new String(new Random().nextInt() + "");
			condition.signalAll();
			index ++;
		} finally {
			lock.unlock();
		}
	}
	
	/**
	 * 从缓冲区拿数据
	 */
	public void get(){
		lock.lock();
		try{
			while(index == 0){
				try {
					System.out.println("get--------" + Thread.currentThread().getName() + "处于阻塞");
					condition.await();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			index --;
			System.out.println("get---------" + Thread.currentThread().getName() + "唤醒阻塞");
			condition.signalAll();
			
			
		} finally {
			
			lock.unlock();
		}
	}
}


第二种解决方案,用java 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();
     }
   } 
 }



请注意,

(ArrayBlockingQueue 类提供了这项功能,因此没有理由去实现这个示例类。)
[size=medium][/size]
分享到:
评论

相关推荐

    深入Synchronized和java.util.concurrent.locks.Lock的区别详解

    Synchronized和java.util.concurrent.locks.Lock都是Java中用于实现线程同步的关键字和接口,它们的主要目标是保证多线程环境下的数据一致性与并发安全。然而,两者在使用方式、控制粒度以及灵活性方面存在显著差异...

    Java lock同步锁使用实例解析

    在Java中,Lock是一个接口,而synchronized是Java中的关键字,两者都可以用于实现同步锁,但它们有着不同的实现机制和特点。 Java lock同步锁的使用实例解析中,主要介绍了Lock和synchronized两种同步锁机制的异同...

    java中的同步和异步的异同共4页.pdf.zip

    Java中实现同步的方法有多种,如synchronized关键字、Lock接口(如ReentrantLock)以及Semaphore等。 异步编程则允许线程在等待某个操作完成时继续执行其他任务。在异步模型中,调用方法不会立即返回结果,而是通过...

    java中的同步和异步的异同.docx

    ### Java中的同步与异步详解 #### 一、同步机制详解 ##### 1. 同步的基本概念 在Java中,同步是指多个线程在访问共享资源时采取的一种机制,目的是确保同一时间只有一个线程能够访问共享资源。这种机制通过锁...

    计算机后端-Java-Java高并发从入门到面试教程-发课程资料.zip

    - **Java线程**:学习如何在Java中创建、启动、停止线程,理解Thread类和Runnable接口。 - **线程同步**:掌握synchronized关键字的用法,包括锁对象、同步代码块和同步方法。 2. **并发控制** - **wait/notify...

    Lock详解.pdf

    在Java中,同步等待队列基于CLH(Craig, Landin, and Hagersten)队列,这是一种高效的双向链表结构。 - **条件等待队列**:通过Condition接口实现,允许线程在满足特定条件时等待,条件满足时再唤醒。Condition...

    多线程,高并发.pdf

    1. stop() 和 suspend() 方法为何不推荐使用? 2. sleep() 和 wait() 有什么区别? 3. 同步和异步有何异同,...5. 简述 synchronized 和 java.util.concurrent.locks.Lock 的异同? 6. 概括的解释下线程的几种可用状态。

    java多线程编程实例_Source

    在Java中,线程是程序的执行流,每个线程都有自己的程序计数器、虚拟机栈、本地方法栈和一部分堆内存。Java提供了两种创建线程的方式:继承Thread类和实现Runnable接口。实例中可能涵盖了这两种方式的使用,并通过...

    简单聊聊Synchronized和ReentrantLock锁.docx

    本文将深入探讨Synchronized关键字锁和ReentrantLock锁的异同、功能特性以及它们在实际应用中的适用场景。 首先,Synchronized是一种内置的Java关键字,它提供了简单而强大的线程同步机制。当一个线程进入一个由...

    JAVA面试_多线程,高并发相关14个问题.pdf

    在Java多线程和高并发领域,面试中常常会涉及到一系列关键问题,这些问题涉及到线程安全、并发控制以及锁机制。以下是对这些问题的详细解答: 1. **stop() 和 suspend() 方法为何不推荐使用?** - `stop()` 方法不...

    java多线程知识讲解及练习题

    5. synchronized 和 java.util.concurrent.locks.Lock 的异同 主要相同点:Lock 能完成 synchronized 所实现的所有功能;主要不同点:Lock 有比 synchronized 更精确的线程语义和更好的性能。synchronized 会自动...

    java多线程,高并发面试题.pdf

    #### 五、简述 `synchronized` 和 `java.util.concurrent.locks.Lock` 的异同? - **相同点**: - `Lock` 接口提供的实现能够完成 `synchronized` 提供的所有功能。 - **不同点**: - `Lock` 提供了更灵活和更...

    120个Java经典面试题和答案

    以上只是部分Java面试中的常见知识点,实际面试中还可能涉及反射、并发编程、Spring框架等更高级的主题。通过深入学习和实践这些知识,将有助于在面试中脱颖而出。而提供的两个PDF文件,"120个Java经典面试题和答案...

    JAVA面试题最全集,JAVA面试题最全集

    - Java中的多线程机制,提高程序的并发执行能力。 #### 8. 文件加密技术 - 使用加密算法保护文件的安全性。 #### 9. 软件开发生命周期 - 包括需求分析、设计、编码、测试和维护等阶段。 #### 10. 路由协议 - ...

    2021年Java大厂面试题整理大全

    1. 接口与抽象类:比较接口和抽象类的异同,理解它们在设计模式中的应用。 2. 多态性:深入理解多态的实现方式和好处,如方法重载和方法覆盖。 3. 泛型:学习泛型的使用,如何限制类型参数,以及泛型通配符。 三、...

    java开发面试合集-自己整理

    - 接口与抽象类:比较接口和抽象类的异同,理解它们在设计中的应用场景。 2. **Java进阶** - 泛型:学习泛型的概念,理解其在代码复用和类型安全上的作用。 - 集合框架:深入研究ArrayList、LinkedList、HashSet...

    Java面试测试题目2018张大成总结

    synchronized和java.util.concurrent.locks.Lock的异同 - **synchronized**:关键字,自动释放锁。 - **Lock**:接口,提供了更高级别的并发控制功能。 #### 48. 如果main方法被声明为private会怎样 - `main`方法...

    Java后端技术面试汇总-副本.pdf

    同时,对Java中并发控制的关键技术synchronized和lock的区别进行了分析。还介绍了CAS无锁机制,乐观锁和悲观锁的概念,原子操作类的应用,以及ABA问题的解释和解决方法。此外,JDK8中并发包的新特性也是这一部分的...

    JAVA面试题解惑系列.zip

    而标签中的"C#"可能表示虽然主要讨论的是Java,但可能也会对比或提及C#的相关知识,例如两种语言在某些特性和设计上的异同。 文件名称"JAVA面试题解惑系列"和"G"可能代表了文件夹或者文档的前缀,具体的面试题和...

Global site tag (gtag.js) - Google Analytics