以前研究过并发编程,但是没有深入,这次有时间了深入研究下。并发编程中只要掌握两个点就好了,一个是线程之间的互斥,一个是线程的通信。
1、互斥: 互斥的概念就是当线程A在执行某个方法时,只有当A完全执行完之后其他的线程才可以访问这个方法,如果A没有执行完,那么其他要访问这个方法的线程将阻塞。
2、通信:如果要很多线程都阻塞了,那么当A执行完之后应该怎么办呢?是让A线程继续执行还是随机选取一个线程执行?这里就是线程之间的通信。
互斥
现在使用的互斥的工具有两个,一个是synchronized,一个是lock(java.util.conrrent.locks.Lock)。
synchronized:可以用在方法上,也可以用在方法体内部。这个的意思是获取某个对象的监视器,进入这个方法(或者被synchronized包含的方法体)必须要获得这个对象的监视器(monitor)。如果是用在方法上的,比如 public void synchronzed aa(){} 那么获得的是这个方法的实例的对象的监视器(也就是aa这个方法所在类的当前实例的监视器);在方法体内比如 public void aa(){ synchronized(someObject) {//do something}},就可以设置要同步的对象(也就是要获取谁的监视器)。当某个对象的监视器没有释放(也就是当前有个线程在执行某个带有synchronized的方法并且没有执行完),其他的线程不能获得监视器也就无法执行这个方法。只有当这个线程执行完成或者是调用了wait()方法之后才会释放这个监视器,然后先前被阻塞的线程获得这个监视器并继续执行。
lock:为什么有了synchronized还要有lock呢?一定是因为lock可以完成synchronized不可以完成的。synchronized有一个很大的缺陷,即某些只读的操作也会被阻塞。举个例子,对于某些缓存的框架,比如hibernate的二级缓存在查询时会先进性判断id=1的在缓存中是否存在,如果不存在的话就会从DB中查找,如果存在则直接从缓存中获得,这样就会提高效率。在这个例子中如果不适用同步的限制,就会出现多次查找的问题,比如下图中,如果有多个线程同时执行这个get(String id)方法,就会可能出现查询多次的情况。
public Class Test12161615{ //用于从DB中查找的dao实例 private Dao dao = xxxx; //缓存 Map<String,Object> cache = new HashMap<String,Object); //根据id查找 public Object get(String id){ Object o = cache.get(id); if(o == null){ //如果没有同步,假设有A线程执行到这里后B线程执行该方法,B到这里后也停止C在执行......o==null的条件都成立,所以就会执行多次查找,所以上锁是必须的。 o = dao.queryById(id); cache.put(o.getId(),o); } return o; } }
如果上的是synchronized的锁,可以解决上面的问题,但是又会出现新的问题。
public Class Test12161615{ //用于从DB中查找的dao实例 private Dao dao = xxxx; //缓存 Map<String,Object> cache = new HashMap<String,Object); //根据id查找 //添加了synchronized之后,某个时间点上只有一个线程可以进入这个方法,所以解决了多次查询的问题。但是当cache中有要查询的id时,即多个线程只是查询的线程时也会被阻塞,造成资源的浪费。 public synchronized Object get(String id){ Object o = cache.get(id); if(o == null){ o = dao.queryById(id); cache.put(o.getId(),o); } return o; } }
所以要用lock来解决这个问题,lock之所以不同于synchronized是因为他区分了读锁和写锁,写锁和写锁,写锁和读锁是互斥的,但是读锁和读锁是不互斥的,这样就解决了并发读时的阻塞问题,并且不会引起多次写的问题。
public Class Test12161615{ //用于从DB中查找的dao实例 private Dao dao = xxxx; //缓存 Map<String,String> cache = new HashMap<String,String); Lock lock = new ReentrantReadWriterLock(); public String getFromCache(String key){ String value = null; try { //读取数据,上读锁 lock.readLock().lock(); value = cache.get(key); if(value == null){ //没有数据,要写,上写锁,先释放读锁,因为读锁不能升级为写锁。 lock.readLock().unlock(); try { lock.writeLock().lock();//上写锁 if( value == null){//再次判断,因为其他线程可能已经执行了这个方法, value = getFromDb(); } lock.readLock().lock();//降级为读锁,写锁可以降为读锁。 } finally { lock.writeLock().unlock();//释放写锁,这个时候其他的读线程可以读取了。 } } return value;//在释放读锁之前返回,保证不会被修改。 } finally { lock.readLock().unlock(); } } }
这样就会解决了,需要注意的是ReentranReadWriteLock的用法。读锁和写锁是可以互换的,读锁不可以升级为写锁,即如果已经上了读锁,必须解锁读锁才可以上写锁,否则会报错。但是写锁可以降低为读锁,所以如果已经上了写锁,再次上读锁是可以的。
至此,可以学好线程之间的互斥了,并且用synchronized 或者 lock来实现。
相关推荐
Java并发编程---synchronized关键
62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java...
Java并发编程中的多线程协作机制 在 Java 并发编程中,多线程协作机制是非常重要的一部分。多线程协作机制是指在多线程编程中,多个线程之间如何协作、同步和通信,以达到共同完成某个任务的目的。Java 提供了多种...
Java并发编程-设计原则与模式 pdf格式
Java并发编程实践-电子书-01章.pdf Java并发编程实践-电子书-02章.pdf Java并发编程实践-电子书-03章.pdf Java并发编程实践-电子书-04章.pdf Java并发编程实践-电子书-05章.pdf Java并发编程实践-电子书-06章.pdf ...
本教程“java并发编程-从入门到精通”旨在帮助你深入理解这个领域,并逐步提升你的编程能力。 首先,我们要理解Java并发的基础概念。并发是指一个程序中同时执行的多个线程,这在多核或多处理器系统中尤为常见。...
阿里专家级并发编程架构师级课程,完成课程的学习可以帮助同学们解决非常多的JAVA并发编程疑难杂症,极大的提高JAVA并发编程的效率。课程内容包括了JAVA手写线程池,UC线程池API详解,线程安全根因详解,锁与原子类...
Java并发编程原汁原味英文版,Doug Lea大神经典著作, 内容:Concurrency Models, design forces, Java Designing objects for concurrency Immutability, locking, state dependence, containment, splitting ...
【Java并发编程-并发容器1】 在Java的并发编程中,容器的线程安全是至关重要的。HashMap在多线程环境下可能导致CPU利用率极高,因为它不是线程安全的。HashTable虽然提供了线程安全,但其同步机制导致并发性能较低。...
《Java并发编程实战》是Java并发编程领域的一本经典著作,它深入浅出地介绍了如何在Java平台上进行高效的多线程编程。这本书的源码提供了丰富的示例,可以帮助读者更好地理解书中的理论知识并将其应用到实际项目中。...
Java并发编程是Java开发中的重要领域,特别是在多核处理器和分布式系统中,高效地利用并发可以极大地提升程序的性能和响应速度。以下是对标题和描述中所提及的几个知识点的详细解释: 1. **线程与并发** - **线程*...
《Java并发编程实战》这本书是关于Java语言中并发编程技术的经典著作。它详细介绍了如何在Java环境中有效地实现多线程程序和并发控制机制。在Java平台上,由于其本身提供了强大的并发编程支持,因此,掌握并发编程...
"java并发编程-构建块"这个主题涵盖了使程序能够同时处理多个任务的关键概念和技术。在这个主题下,我们将深入探讨Java中用于构建高效并发应用的核心工具和概念。 1. **线程**:Java中的线程是并发编程的基础,每个...
总结,Java并发编程涵盖了大量的概念和技术,包括线程的创建、同步、通信以及并发工具的使用。理解和掌握这些知识点,是成为一名合格的Java并发程序员的基础。在实际开发中,应结合具体场景选择合适的并发策略,以...
02-JUC高并发编程-JUC概述和进程线程概念(1).mp4 03-JUC高并发编程-JUC概述和进程线程概念(2).mp4$ T/ H9 R! n2 l9 a b 04-JUC高并发编程-JUC概述和进程线程概念(3).mp4 05-JUC高并发编程-Synchronized复习和...
《Java并发编程艺术》这本书深入探讨了Java平台上的并发编程技术。并发编程是现代多核处理器环境下提升软件性能的关键手段,而Java语言提供了丰富的工具和API来支持这一领域。本书旨在帮助开发者理解和掌握如何在...
《Java并发编程实战》是一本深入探讨Java平台并发编程的权威指南。这本书旨在帮助开发者理解和掌握在Java环境中创建高效、可扩展且可靠的多线程应用程序的关键技术和实践。它涵盖了从基本概念到高级主题的广泛内容,...
Java并发编程是Java开发中的重要领域,特别是在多核处理器和分布式系统中,高效地利用并发可以极大地提升程序的性能和响应速度。阿里大牛梁飞编写的《Java并发编程常识》PPT,深入浅出地讲解了这个主题,对开发者来...