Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[建议]lock.lock()应该放在try之前 #287

Closed
tiggerlee2 opened this issue Mar 21, 2018 · 6 comments
Closed

[建议]lock.lock()应该放在try之前 #287

tiggerlee2 opened this issue Mar 21, 2018 · 6 comments

Comments

@tiggerlee2
Copy link

建议新增规则,lock.lock()应该放在try之前:

 lock.lock();
 try {
      doSomething();
 } finally {
       lock.unlock();
 }

如果按照下边写法,当lock.lock()报错时也会进入finally释放锁,根据Lock.unlock()文档,当非锁持有线程调用该方法时会抛出unchecked异常:

try {
      lock.lock();
      doSomething();
 } finally {
       lock.unlock();
 }
@xuantan
Copy link
Collaborator

xuantan commented Apr 3, 2018

@yangguanbao 看下哈

@luyiisme
Copy link

luyiisme commented Apr 3, 2018

@juggernaut0425 @yangguanbao
这个可以写入规范的,第一种也是标准的写法。 第二种,lock()方法或者lock.lockInterruptibly()等加锁方法 ,(依赖具体的实现类)某些特殊情况可能会抛出unchecked异常,程序执行转入到finally块中,因为当前线程没有持有锁,unlock()方法可能(由具体的实现锁而定)会抛异常(比如,IllegalMonitorStateException),这样会丢失掉导致加锁失败的异常(虽然结果都是加锁失败,但异常信息却会不一致)。

@gujin520
Copy link
Contributor

已经采纳了你的建议,非常感谢,我们已经在内部版本中加了此规约描述,云栖大会版本中会出现这个条目,十分感谢你对《阿里巴巴JAVA开发手册》的支持,内容如下:

【强制】在try代码块之前调用Lock实现类的lock()方法,避免由于加锁失败,导致finally调用unlock()抛出异常。
说明:在lock方法中可能抛出uncheck异常,如果放在try代码块中,必然触发finally中的unlock方法的执行,它会调用AQS的tryRelease方法,(取决于具体实现类)。根据Lock接口中的unlock描述,对未加锁的对象解锁抛出unchecked异常,如:IllegalMonitorStateException,虽然都是加锁失败造成程序中断,但是真正加锁出错信息可能被后者覆盖。
反例:
Lock lock = new XxxLock();
preDo();
try {
// 无论加锁是否成功,unlock都会执行
lock.lock();
doSomething();
} finally {
lock.unlock();
}

@hellofreejoe
Copy link

但是如果lock.lock()放在外面,就有可能出现锁了之后最终没有lock.unlock()的情况,这样会造成死锁。

@hellofreejoe
Copy link

也就是说,大伙认为抛出异常的风险、和造成死锁的风险,后者更容易被接受?请指教

@zqq90
Copy link

zqq90 commented Nov 22, 2018

对于:

但是如果lock.lock()放在外面,就有可能出现锁了之后最终没有lock.unlock()的情况,这样会造成死锁。

  • 这就要看 lock.lock() 具体实现是否是单一职责了, 是否是仅仅只完成加锁这一单一职责, 即: .lock() 若抛出任何异常都将始终保证未保持锁状态(或者已撤回锁状态), 反之, 加锁成功程序继续执行

  • lock.lock() 之后必须紧跟 Try-finally , 中间不能有额外的 preDo();

基于以上条件, 似乎不会出现所描述的这个死锁问题, 如有不对也请指教

cc @hellofreejoe

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants