重入锁和公平锁

同步控制的方法除了synchronized外,还可以用重入锁来实现,重入锁的类是java.util.concurrent.locks.ReentrantLock类。调用重入锁的两个方法lock()和unlock()来包裹保护临界区操作,也就是加锁和释放锁的过程是显式的。直接来看一段重入锁的使用代码:

第11行到15行对临界资源value(也就是我们希望得到同步控制的资源)的++操作进行上锁保护,完成value++操作后再释放锁。主函数中建十个线程对同一个对象L1的Value做++操作,最后能保证value的值为10000。

      我们来看一个有趣的现象,假如我们再加一行上锁操作:

我们在11行和12行都有一句lock()上锁的语句,而16行及之后只有一句unlock()语句,编译竟然是通过的,允许结果结果是主函数中一直无法输出value的值。我们稍微改一下代码,加点输出语句看下发生了什么事?

我们在第15行,每次线程对value做完++操作后,都输出以下value的值等于多少来看看,结果我们发现,第一个线程把value++到1000后,就停下来了,剩下的9个线程一直没有执行。原来,重入锁之所以叫重入锁,是因为一个线程可以连续多次获得同一把锁,这把锁是可以重复进入的,所以叫重入锁,上面的代码因为一个线程连续两次获得同一把锁,之后却只释放了一次,所以其实该线程还是占用了这把锁,导致其他线程无法获得锁。如果同一个线程多次获得这个锁,那么释放锁时也要释放相同次数才可以,上面的代码只要再释放一次锁,就能得到正确的允许结果了:

以上就是最简单的使用重入锁,用new ReentrantLock()实例化的锁是不公平的,为什么说不公平?假设线程A申请了锁lock,然后释放了锁lock,接下来当线程A和线程B都去申请锁lock时,是线程A先获得锁还是线程B先获得锁?还是觉得获得锁的顺序是根据所得等待队列来决定?答案是获得锁的线程是随机挑选的,从锁的等待队列中随机挑选,所以说用new ReentrantLock()实例化的锁是不公平的,synchronized关键字进行同步控制的锁也是不公平的。如果想要获得公平锁,就要调用重入锁ReentrantLock的构造函数:

第八行传入个参数true,就是设置公平锁,然后我们建立三个线程,让它们不停地获得锁,在获得锁后“喊”一声,然后释放锁。从运行结果来看,三个线程轮流获得锁,基本上不会出现某一个线程连续两次获得锁的情况,这就是公平锁。但是如果我们把参数true拿走,非公平锁就会出现这样的情况:

某个线程会连续多次获得锁,这对于其他线程来说是不公平的。

      详细代码可以看我的GitHub:

https://github.com/justinzengtm/Multithreading/blob/master/ReenterLock.java

https://github.com/justinzengtm/Multithreading/blob/master/FairLock.java

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值