锁定老帖子 主题:最简单高效的tryLock
精华帖 (0) :: 良好帖 (2) :: 新手帖 (1) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-09-25
asme2u 写道
mercyblitz 写道
asme2u 写道
if(l.tryLock()) { try{ // 这里能有多个线程同时到达? } finally { l.unlock } }mercyblitz 写道 asme2u 写道
mercyblitz 写道
asme2u 写道
hellojinjie 写道
asme2u 写道
ellojinjie 写道
性能应该只与线程执有锁的时间和多少个线程竞争该锁有关,,为什么会和线程如何得到锁有关???
你用tryLock,应该是自旋锁这一类的吧,在我的单核的CPU上,恐怕也不会有什么性能的提高。。。 我实际应用场景是高并发,短占用,如果你应用场景从获取锁到释放锁需要很长的时间,性能不会有多少提高 看来是ReentrantLock 里的tryLock太耗时了,才会使得用AtomicBoolean实现的Lock性能比ReentryLock好 正解,只有符合锁占用的时间与获取锁的时间可比拟时,这个类才有意义,所以我列出了适用场景。 你要看情况, 建议楼主看一下为什么要引入偏向锁,就是为了解决CAS延迟问题。http://blogs.sun.com/dave/entry/biased_locking_in_hotspot 你所说的场景不过是你-client的设置罢了,多核CPU再来试试。 看了一下你的链接,谢谢你的提醒,确实有延迟的问题,如果这么考虑,是否CAS都不可靠了呢?这些个原子类什么时候适用? 在你的代码中,那个逻辑判断是可靠的,但是中间的执行代码是线程不安全的。 PS:CAS是可靠的,它是Wait-free的实现,不过它只能针对单个资源安全,不能作为多语句的原子操作。
是的,代码中没有让线程等待。
CAS是个原子操作,不可能被打断,那怎么可能会有两个线程执行 lock.compareAndSet(true, false)这个都返回true呢?
恩,你是对的,不过中间代码端的资源没有同步主存。 |
|
返回顶楼 | |
发表时间:2010-09-25
的确,中间的那段,我们开发的时候意识到了,使用的是一个volatile变量作为标志繁忙状态而已,可能在别的场合下,中间的那段会发生CPU缓存中的变量与内存中的不一致的情况
|
|
返回顶楼 | |
发表时间:2010-09-25
asme2u 写道 的确,中间的那段,我们开发的时候意识到了,使用的是一个volatile变量作为标志繁忙状态而已,可能在别的场合下,中间的那段会发生CPU缓存中的变量与内存中的不一致的情况
恩,volatile 还是不行,还是因为原子操作的问题。 |
|
返回顶楼 | |
发表时间:2010-09-25
mercyblitz 写道 asme2u 写道 的确,中间的那段,我们开发的时候意识到了,使用的是一个volatile变量作为标志繁忙状态而已,可能在别的场合下,中间的那段会发生CPU缓存中的变量与内存中的不一致的情况
恩,volatile 还是不行,还是因为原子操作的问题。 volatile不支持并发修改,但是能保证修改被立刻看到,又为何不行? 不过以前在那里看到说JDK5.0前volatile实现得不好,没太关注,早不用老版本了 |
|
返回顶楼 | |
发表时间:2010-09-25
最后修改:2010-09-25
软件包 java.util.concurrent.atomic 的描述:
类的小工具包,支持在单个变量上解除锁定的线程安全编程。事实上,此包中的类可将 volatile 值、字段和数组元素的概念扩展到那些也提供原子条件更新操作的类。 楼主的这个锁和自旋锁还是有区别的,因为用户有机会定制"就算拿不到锁,我要做的事情" |
|
返回顶楼 | |
发表时间:2010-09-25
mxswl 写道 软件包 java.util.concurrent.atomic 的描述:
类的小工具包,支持在单个变量上解除锁定的线程安全编程。事实上,此包中的类可将 volatile 值、字段和数组元素的概念扩展到那些也提供原子条件更新操作的类。 楼主的这个锁和自旋锁还是有区别的,因为用户有机会定制"就算拿不到锁,我要做的事情" public void lock() { for (;;) { if (lock.compareAndSet(true, false)) { break; } try { Thread.sleep(0, 10); } catch (InterruptedException e) { e.printStackTrace(); } } } 模拟自旋锁,可否? |
|
返回顶楼 | |
发表时间:2010-09-25
asme2u 写道 mercyblitz 写道 asme2u 写道 的确,中间的那段,我们开发的时候意识到了,使用的是一个volatile变量作为标志繁忙状态而已,可能在别的场合下,中间的那段会发生CPU缓存中的变量与内存中的不一致的情况
恩,volatile 还是不行,还是因为原子操作的问题。 volatile不支持并发修改,但是能保证修改被立刻看到,又为何不行? 不过以前在那里看到说JDK5.0前volatile实现得不好,没太关注,早不用老版本了 volatile 支持并发修改,并且保证了JSL规范中定义的Happens-before关系。 但是由于它是偏续关系,所以不满足“因果一致性” 比如: volatile boolean b1; volatile boolean b2; 如果b2依赖于b1,比如 { //b1可能是true或者false; b2 = !b1; //如果是volatile的关系,b2不确定。但是如果b1,b2在同步中,那么b1和b2的值都被锁定了。 } |
|
返回顶楼 | |
发表时间:2010-09-25
mercyblitz 写道 asme2u 写道 mercyblitz 写道 asme2u 写道 的确,中间的那段,我们开发的时候意识到了,使用的是一个volatile变量作为标志繁忙状态而已,可能在别的场合下,中间的那段会发生CPU缓存中的变量与内存中的不一致的情况
恩,volatile 还是不行,还是因为原子操作的问题。 volatile不支持并发修改,但是能保证修改被立刻看到,又为何不行? 不过以前在那里看到说JDK5.0前volatile实现得不好,没太关注,早不用老版本了 volatile 支持并发修改,并且保证了JSL规范中定义的Happens-before关系。 但是由于它是偏续关系,所以不满足“因果一致性” 比如: volatile boolean b1; volatile boolean b2; 如果b2依赖于b1,比如 { //b1可能是true或者false; b2 = !b1; //如果是volatile的关系,b2不确定。但是如果b1,b2在同步中,那么b1和b2的值都被锁定了。 } 谢谢,你这么一说我明白了,如果只是对一个volatile操作就如我所说的,仅仅一个标志而已,就没问题了吧 |
|
返回顶楼 | |
发表时间:2010-09-25
asme2u 写道 mercyblitz 写道 asme2u 写道 mercyblitz 写道 asme2u 写道 的确,中间的那段,我们开发的时候意识到了,使用的是一个volatile变量作为标志繁忙状态而已,可能在别的场合下,中间的那段会发生CPU缓存中的变量与内存中的不一致的情况
恩,volatile 还是不行,还是因为原子操作的问题。 volatile不支持并发修改,但是能保证修改被立刻看到,又为何不行? 不过以前在那里看到说JDK5.0前volatile实现得不好,没太关注,早不用老版本了 volatile 支持并发修改,并且保证了JSL规范中定义的Happens-before关系。 但是由于它是偏续关系,所以不满足“因果一致性” 比如: volatile boolean b1; volatile boolean b2; 如果b2依赖于b1,比如 { //b1可能是true或者false; b2 = !b1; //如果是volatile的关系,b2不确定。但是如果b1,b2在同步中,那么b1和b2的值都被锁定了。 } 谢谢,你这么一说我明白了,如果只是对一个volatile操作就如我所说的,仅仅一个标志而已,就没问题了吧 对的,如果只有一个变量的话,也没有必要任何辅助代。 |
|
返回顶楼 | |
发表时间:2010-09-25
有判断语句,不光只有一条修改语句
大致是这样的意思: if(l.tryLock()) { if(!busyFlag) { busyFlag = true; } l.unlock(); } 那个标志是个volatile |
|
返回顶楼 | |