java高并发

Posted zhangsancat

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java高并发相关的知识,希望对你有一定的参考价值。

对于我们开发的网站,如果网站的访问量非常大的话,那么我们就需要考虑相关的并发访问问题了,然而并发问题是令我们大多数程序员头疼的问题,但话又说回来了,既然逃避不掉,那我们就坦然面对吧~今天就让我们深入研究一下常见的并发和同步问题吧。

 

一、同步和异步的区别和联系

    为了更好的理解同步和并发问题,我们需要先掌握两个重要的概念:同步、异步

    同步:可以理解为在执行完一个函数或者方法后,一直等待系统返回值或消息,这是程序是处于阻塞的状态,只有接收到系统的返回值或者消息后,才会继续往下执行。

    异步:执行完函数活方法后,不必阻塞性的等待返回值或消息,只需要向系统委托一个异步过程,那么系统接收到返回值或消息时,就会自动触发委托的异步过程,从而完成一个完整的流程。

 

    同步在一定程度上可以看做是单线程,这个线程请求一个方法后,就等待这个方法给他回复,否则不往下执行(死心眼子)。

    异步在一定程度上可以看做是多线程(废话,一个线程怎么叫异步),请求一个方法后就不管了,继续执行接下来的其他方法。

    

    同步就一件事、一件事、一件事的做。

    异步就是做一件事情,不影响做其他的事情。

    例如:吃饭和说话是同步的,只能一件事一件事的来,因为只有一张嘴。吃饭和听音乐是异步的,听音乐不影响我们吃饭。

  

  对于java程序员来说,我们经常见到同步关键字synchronize,假如这个同步的监视对象是一个类,当一个对象A在访问这个类里面的同步方法,此时另外一个对象B也想访问这个类里面的这个同步方法,就会进入阻塞,只有等待前一个对象执行完该同步方法后当前对象才能够继续执行该方法。这就是同步。

  相反,如果方法前没有同步关键字修饰的话,那么不同的对想就可以在同一时间访问同一个方法,这就是异步。

 

再补充一下,脏数据和不可重复读的概念:

  1、脏数据

    脏读是指:一个事务正在访问数据,并且对数据进行了修改,而这个修改还有提交到数据库中,这时另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的数据是脏数据(Dirty Data),脏数据所做的操作可能是不正确的。

  2、不可重复读

    不可重复读是指:在一个事务内,多次读同一条数据。这个事务还没有结束时,另外一个事务也访问了该数据,那么,在第一个事务中两次读数据之间,由于第二个事务的修改,导致第一个事务两次读到数据可能不一样。这样就发生了在同一个事务内,两次读到的数据是不一样的,因此称为不可重复读。

 

二、如何处理并发和同步

  今天讲的如何处理并发和同步问题主要是通过锁机制去解决。我们需要明白锁机制有两个层面:

  第一是代码层面,如java中的同步锁,典型的就是同步关键字synchronize(还有Lock等)。 感兴趣的可以参考: http://www.cnblogs.com/xiohao/p/4151408.html

  第二是数据库层面上,比较典型的就是悲观锁和乐观锁,这里重点研究一下悲观锁(传统的物理锁)和乐观锁,这两个锁:

  1. 悲观锁(Pessimistic Locking)

    悲观锁正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及外部系统的事务)的修改持保守状态,因此,在整个数据处理过程中,将数据处于锁定状态。

    悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则即使在本系统中实现了加锁机制,也无法保证外部系统会修改数据)。

  一个典型的依赖数据库悲观锁调用:select * from account where name=‘zhangsan‘ for update;

  整条sql锁定了account表中所有符合检索条件(name=‘zhangsan‘)的记录;本次事务提交之前(事务提交会释放事务过程中的锁),外界无法修改这些记录。

hibernate的悲观锁,也是基于数据库的锁机制实现的,下面代码实现了对查询记录的加锁:

String hqlStr ="from TUser as user where user.name=‘zhangsan‘ ";
Query query = session.createQuery(hqlStr);
query.setLockMode("user",LockMode.UPGRADE); // 加锁
List userList = query.list();// 执行查询,获取数据

query.setLocalMode 对查询语句中特定别名所对应的记录进行加锁(我们对TUser类指定了一个别名“user”),这里也就是多所有的返回的记录加锁。
观察运行期的hibernate,生成的sql语句:

    

    

 

  

 

 

 

  

 

以上是关于java高并发的主要内容,如果未能解决你的问题,请参考以下文章

写了4年的Java代码,高并发都不会,你还做什么程序员?

并发与高并发-并发模拟代码

JAVA的高并发编程

Java并发编程与高并发解决方案

Java高并发之同步异步

多线程&高并发查看Java代码对应的汇编指令教程