java中Rlock类的使用_java中的lock和synchronized区别是什么

void await()//将该线程放到条件的等待集中void signalAll()//解除该条件的等待集中的所有线程的阻塞状态void signal()//从该条件的等待集中随机地选择一个线程,解除其阻塞状态=====================================================================synchronized关键字在前面一节中,介绍了如何使用Lock和Condition对象,在进一步深入之前,总结一下有关锁和条件的关键之处:1.锁用来保护代码片段,任何时刻只能有一个线程执行被保护的代码2.锁可以管理试图进入被保护代码段的线程3.锁可以拥有一个或多个相关的条件对象4.每个条件对象管理那些已经进入被保护的代码段但还不能运行的线程Lock和Condition接口被天际到Java5.0中,这也向程序设计人员提供了攻读的封锁控制。然而,大多数情况下,并不需要那样的控制,并且可以使用一种嵌入到Java语言内部的机制。从1.0版开始,Java中的每一个对象都有一个内部锁。如果一个方法用synchronized关键字声明,那么对象的锁将保护整个方法。也就是说,要调用该方法,线程必须获得内部的对象锁。换句话说:public synchronized void method(){method body}pblic void method(){this.intrinsicLock.lock();try{method body;}finally{this.intrinsicLock.unlock();}}例如:可以简单地声明Bank类的transfer方法为synchronized,而不是使用一个显示的锁,内部对象锁只有一个相关条件,wait方法添加一个线程到等待集中,notifyAll/notify方法解除等待线程的阻塞状态。换句话说,调用wait或notifyAll等价于intrinsicCondition.await();intrinsicCondition.signalAll();class Bank{public synchronized void transfer(int from,int to,int amout)throws InterrupterException{while(accounts[from]中存储银行余额。这里有一个transfer方法的原始实现:public void transfer(Vector accounts,int from,int to,int amount){accounts.set(from,accounts,get(from)-amount);accounts.set(to,accounts.get(to)+amount);System.out.println("...");}Vector类的get和set方法是同步的,但是,这对于我们并没有什么帮助,在第一次对get的地哦啊用已经完成之后,一个线程完全可能在transfer方法中被剥夺运行权。于是,另一个线程可能在想通过的存储位置存入不同的值,但是,我们可以截获这个锁:public void transfer(Vector accounts,int from,int to,int amout){synchronized(accounts){accounts.set(from,accounts.get(from)-amount);accounts.set(to,accounts.get(from)+amount);}System.out.println("...");}这个方法可以工作,但是他完全依赖于这样一个事实,Vector类对自己的所有课修改方法都使用内部锁,然而,这是真的吗?Vector类的文档没有给这样的承诺,不得不仔细研究源码并希望将来的版本能介绍非同步的可修改方法,如你所见,客户端锁定是非常脆弱的,通常不推荐使用。=======================================================================读/写锁java.util.concurrent.locks包定义了两个锁类,我们已经讨论的ReentrantLock类和ReentrantReadWriteLock类,如果很多线程从一个数据结构读取数据而很少线程修改其中数据的话,后者是十分有用的。在这种情况下,允许对读者线程共享访问是合适的。当然,写者线程依然必须是互斥访问的。下面是使用读写锁的必要步骤:1.构造一个ReentranReadWriteLock对象private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();2.抽取读写锁:private Lock readLock = rwl.readLock();private Lock writeLock = rwl.writeLock();3.对所有的访问者加读锁public double getTotalBalance(){readLock.lock();try{...}finally{readLock.unlock();}}4.对所有的修改者加锁public void tranfer(...){writeLock.lock();try{...}finally{writeLock.unlock();}}Lock readLock() 得到一个可以被多个读操作共用的读锁,但会排斥所有写操作Lock writeLock()得到一个写锁,排斥所有其他的读操作和写操作===================================================================阻塞队列现在,读者已经看到了形成Java并发程序设计基础的底层构建块。然而,对于实际编程来说,应该尽可能远离底层结构,使用有并发出处理的专业人士实现的较高层次的结构要方便得多,要安全的多。===================================================================线程池newCachedThreadPool方法构建了一个线程池,对于每个任务,如果有空闲线程可用,立即让它执行任务,如果没有可用的空闲线程,则创建一个新的线程。newFixedThreadPool方法构建一个具有固定大小的线程池。如果提交的任务数多于空闲的线程数,那么把得不到的服务的任务放置到队列中,当其他任务完成以后再运行他们。(这最好自己写一下)===================================================================1、ReentrantLock 拥有Synchronized相同的并发性和内存语义,此外还多了 锁投票,定时锁等候和中断锁等候

线程A和B都要获取对象O的锁定,假设A获取了对象O锁,B将等待A释放对O的锁定,

如果使用 synchronized ,如果A不释放,B将一直等下去,不能被中断

如果 使用ReentrantLock,如果A不释放,可以使B在等待了足够长的时间以后,中断等待,而干别的事情

ReentrantLock获取锁定与三种方式:

a) lock(), 如果获取了锁立即返回,如果别的线程持有锁,当前线程则一直处于休眠状态,直到获取锁

b) tryLock(), 如果获取了锁立即返回true,如果别的线程正持有锁,立即返回false;

c)tryLock(long timeout,TimeUnit unit), 如果获取了锁定立即返回true,如果别的线程正持有锁,会等待参数给定的时间,在等待的过程中,如果获取了锁定,就返回true,如果等待超时,返回false;

d) lockInterruptibly:如果获取了锁定立即返回,如果没有获取锁定,当前线程处于休眠状态,直到或者锁定,或者当前线程被别的线程中断

2、synchronized是在JVM层面上实现的,不但可以通过一些监控工具监控synchronized的锁定,而且在代码执行时出现异常,JVM会自动释放锁定,但是使用Lock则不行,lock是通过代码实现的,要保证锁定一定会被释放,就必须将unLock()放到finally{}中

3、在资源竞争不是很激烈的情况下,Synchronized的性能要优于ReetrantLock,但是在资源竞争很激烈的情况下,Synchronized的性能会下降几十倍,但是ReetrantLock的性能能维持常态;

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值