`
suichangkele
  • 浏览: 199765 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java并发编程-1

    博客分类:
  • java
阅读更多

以前研究过并发编程,但是没有深入,这次有时间了深入研究下。并发编程中只要掌握两个点就好了,一个是线程之间的互斥,一个是线程的通信。

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关键字

    Java并发编程---synchronized关键

    62-Java并发编程实战

    62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java...

    Java并发编程-3.pdf

    Java并发编程中的多线程协作机制 在 Java 并发编程中,多线程协作机制是非常重要的一部分。多线程协作机制是指在多线程编程中,多个线程之间如何协作、同步和通信,以达到共同完成某个任务的目的。Java 提供了多种...

    Java并发编程-设计原则与模式

    Java并发编程-设计原则与模式 pdf格式

    Java并发编程实践-电子书

    Java并发编程实践-电子书-01章.pdf Java并发编程实践-电子书-02章.pdf Java并发编程实践-电子书-03章.pdf Java并发编程实践-电子书-04章.pdf Java并发编程实践-电子书-05章.pdf Java并发编程实践-电子书-06章.pdf ...

    java并发编程-从入门到精通

    本教程“java并发编程-从入门到精通”旨在帮助你深入理解这个领域,并逐步提升你的编程能力。 首先,我们要理解Java并发的基础概念。并发是指一个程序中同时执行的多个线程,这在多核或多处理器系统中尤为常见。...

    阿里专家级并发编程架构师课程 彻底解决JAVA并发编程疑难杂症 JAVA并发编程高级教程

    阿里专家级并发编程架构师级课程,完成课程的学习可以帮助同学们解决非常多的JAVA并发编程疑难杂症,极大的提高JAVA并发编程的效率。课程内容包括了JAVA手写线程池,UC线程池API详解,线程安全根因详解,锁与原子类...

    Java并发编程-Doug Lea

    Java并发编程原汁原味英文版,Doug Lea大神经典著作, 内容:Concurrency Models, design forces, Java Designing objects for concurrency Immutability, locking, state dependence, containment, splitting ...

    Java并发编程-并发容器1

    【Java并发编程-并发容器1】 在Java的并发编程中,容器的线程安全是至关重要的。HashMap在多线程环境下可能导致CPU利用率极高,因为它不是线程安全的。HashTable虽然提供了线程安全,但其同步机制导致并发性能较低。...

    java并发编程实战源码,java并发编程实战pdf,Java

    《Java并发编程实战》是Java并发编程领域的一本经典著作,它深入浅出地介绍了如何在Java平台上进行高效的多线程编程。这本书的源码提供了丰富的示例,可以帮助读者更好地理解书中的理论知识并将其应用到实际项目中。...

    java并发编程2

    Java并发编程是Java开发中的重要领域,特别是在多核处理器和分布式系统中,高效地利用并发可以极大地提升程序的性能和响应速度。以下是对标题和描述中所提及的几个知识点的详细解释: 1. **线程与并发** - **线程*...

    Java 并发编程实战.pdf

    《Java并发编程实战》这本书是关于Java语言中并发编程技术的经典著作。它详细介绍了如何在Java环境中有效地实现多线程程序和并发控制机制。在Java平台上,由于其本身提供了强大的并发编程支持,因此,掌握并发编程...

    java并发编程-构建块

    "java并发编程-构建块"这个主题涵盖了使程序能够同时处理多个任务的关键概念和技术。在这个主题下,我们将深入探讨Java中用于构建高效并发应用的核心工具和概念。 1. **线程**:Java中的线程是并发编程的基础,每个...

    java并发编程-超级大全整理

    总结,Java并发编程涵盖了大量的概念和技术,包括线程的创建、同步、通信以及并发工具的使用。理解和掌握这些知识点,是成为一名合格的Java并发程序员的基础。在实际开发中,应结合具体场景选择合适的并发策略,以...

    java高级技术JUC高并发编程教程2021(1.5G)

    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平台上的并发编程技术。并发编程是现代多核处理器环境下提升软件性能的关键手段,而Java语言提供了丰富的工具和API来支持这一领域。本书旨在帮助开发者理解和掌握如何在...

    《java 并发编程实战高清PDF版》

    《Java并发编程实战》是一本深入探讨Java平台并发编程的权威指南。这本书旨在帮助开发者理解和掌握在Java环境中创建高效、可扩展且可靠的多线程应用程序的关键技术和实践。它涵盖了从基本概念到高级主题的广泛内容,...

    Java并发编程常识-梁飞.rar

    Java并发编程是Java开发中的重要领域,特别是在多核处理器和分布式系统中,高效地利用并发可以极大地提升程序的性能和响应速度。阿里大牛梁飞编写的《Java并发编程常识》PPT,深入浅出地讲解了这个主题,对开发者来...

Global site tag (gtag.js) - Google Analytics