前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java多线程加锁的简单处理办法 原

java多线程加锁的简单处理办法 原

作者头像
尚浩宇
发布2018-08-17 10:05:56
1.5K0
发布2018-08-17 10:05:56
举报
文章被收录于专栏:杂烩杂烩

    当对数据修改时,如果两个线程同时去修改同一条数据,这样产生的结果就不是我们预期的结果。这时候就需要对修改操作进行加锁,让jvm里同一时刻只能有一个线程能够执行修改方法。

    下面是一个未加锁的修改方法:   

代码语言:javascript
复制
public void update(Entry entry){
    dao.update(entry);
}

    现在讨论下传统的加锁方法。我们知道每一个对象都隐含了一个锁,那就是对象本身。我们可以在方法体上加上同步字段synchronized

代码语言:javascript
复制
public synchronized void update(Entry entry){
    dao.update(entry);
}

但如果方法里代码很多,那么加在方法上会锁住很多代码,我们可以使用同步块

代码语言:javascript
复制
public void update(Entry entry){
    dobefore();
    synchronized(this){
        dao.update(entry);
    }
    doend(); 
}

    而需要注意的是如果一个类中存在多个同步方法,那么所有同步方法的锁都是对象本身,也就是说当执行update的时候,别的线程不仅不能执行update连类中别的同步方法也不能使用。当然也可以使用一点技巧去规避这个问题,比如使用其他锁。

    我们这篇博客说得不是上面的方法,而是另外一个位于java.util.concurrent.locks包下的ReentrantLock。

    官方是这么说的:

    一个可重入的互斥锁 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大。     ReentrantLock 将由最近成功获得锁,并且还没有释放该锁的线程所拥有。当锁没有被另一个线程所拥有时,调用 lock 的线程将成功获取该锁并返回。如果当前线程已经拥有该锁,此方法将立即返回。可以使用 isHeldByCurrentThread() 和 getHoldCount() 方法来检查此情况是否发生。     此类的构造方法接受一个可选的公平 参数。当设置为 true 时,在多个线程的争用下,这些锁倾向于将访问权授予等待时间最长的线程。否则此锁将无法保证任何特定访问顺序。与采用默认设置(使用不公平锁)相比,使用公平锁的程序在许多线程访问时表现为很低的总体吞吐量(即速度很慢,常常极其慢),但是在获得锁和保证锁分配的均衡性时差异较小。不过要注意的是,公平锁不能保证线程调度的公平性。因此,使用公平锁的众多线程中的一员可能获得多倍的成功机会,这种情况发生在其他活动线程没有被处理并且目前并未持有锁时。还要注意的是,未定时的 tryLock 方法并没有使用公平设置。因为即使其他线程正在等待,只要该锁是可用的,此方法就可以获得成功。

    使用它也很简单,你可以用如下结构来使用他:   

代码语言:javascript
复制
class X {
   private final ReentrantLock lock = new ReentrantLock();
   // ...

   public void m() { 
     lock.lock();  // block until condition holds
     try {
       // ... method body
     } finally {
       lock.unlock()
     }
   }
 }

    常用的方法就如上面所说的一样,lock和unlock   

代码语言:javascript
复制
lock
public void lock()
获取锁。
如果该锁没有被另一个线程保持,则获取该锁并立即返回,将锁的保持计数设置为 1。
如果当前线程已经保持该锁,则将保持计数加 1,并且该方法立即返回。
如果该锁被另一个线程保持,则出于线程调度的目的,禁用当前线程,并且在获得锁之前,该线程将一直处于休眠状态,此时锁保持计数被设置为 1。
指定者:
接口 Lock 中的 
lock

unlock
public void unlock()
试图释放此锁。
如果当前线程是此锁所有者,则将保持计数减 1。如果保持计数现在为 0,则释放该锁。如果当前线程不是此锁的持有者,则抛出 IllegalMonitorStateException。
指定者:
接口 Lock 中的 
unlock
抛出:
IllegalMonitorStateException - 如果当前线程没有保持此锁

    当然他还有别的很多方法,需要的话可以自己去看看。

    对比synchronized这个锁是独立的,在一个类中多个同步块之间都是独立的,互不影响。最后说一句,因为同步块会让一段代码同一时刻只能有一个线程使用,多线程同时访问,一个使用其他都是等待状态,那么就存在一个性能问题。如果理解原子性,又那么牛X,利用原子性写出避免同步的免锁代码,什么synchronized啊,ReentrantLock啊,都是浮云。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015/06/24 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档