ReentrantLock:单线程应用程序中的锁定/解锁速度
我正在使用一些 ReentrantLock 来同步跨多个线程对列表的访问。我只是
try {
lock.lock();
... modify list here
} finally {
lock.unlock();
}
到处写一个通用的。我只是注意到,代码中的大多数列表将仅由单个(gui 调度)线程使用。
现在我不确定在这些情况下是否应该删除锁,因为它可能会加快我的代码速度。 ReentrantLock 有多快?如果线程本身是锁的“先前所有者”,即使他解锁()它,lock()操作是否会更快?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
不管它有多快,它肯定会比不加锁慢,哪怕只是慢一点。我个人更喜欢正确性而不是速度增益(速度增益不会很多),并保持代码原样(特别是如果它已经经过测试),除非您已经确定“锁定”是一个瓶颈。
No matter how fast it is, it would certainly be slower than no locking, if just by a very small amount. I would personally prefer correctness over speed gain (which won't be a lot) and keep the code the way it is (especially if it is already tested) unless you have identified "locking" to be a bottleneck.
3件事:
lock.lock()应该在
try
块之外。如果你运行在单核CPU上,锁定是非常便宜的。然后,根据 CPU 架构,获取/释放可能会很便宜,也可能不太便宜。 Nehalem+ 还不错。
如果您不需要其他任何东西的锁,
synchronized
可能是更好的方法,因为 JVM 可以在单线程应用程序中粗化监视器和/或偏向 lock()em。同样,偏向锁的性能因 CPU 架构而异。3 things:
lock.lock() should be outside the
try
block.if you run on a single core CPU locking is very cheap. Then depending on the CPU architecture the acquire/release might be cheap or not so much. Nehalem+ is sorta ok.
if you do not need locks for anything else
synchronized
could be a better approach as the JVM can coarsen the monitors and/or bias lock() 'em in a single threaded application. Again the performance of biased locks greatly varies on the CPU architecture.如果没有争用,获取和释放锁的成本相当低。我想说你不必担心性能影响。
If there is no contention, acquiring and releasing locks is quite inexpensive. I'd say you needn't worry about the performance implications.
我真的不明白你的应用程序是单线程还是多线程。标题说的是一件事,从正文我们可以推断出另一件事。我假设您正在使用多个线程(否则,这个问题就没有意义——为什么要在……少于 2 个线程之间使用同步?!)。
可能存在比性能更大的问题。 可见性。
您没有提供有关
...修改列表...
的代码部分的任何详细信息,但是了解详细信息非常重要:取决于您的操作方式也就是说,如果您删除锁定,可能会发生的情况是:一个线程修改了列表,而另一个线程永远不会看到这些修改(或看到部分、很可能不一致的修改)。您似乎缺少的同步方面是,除非使用某些特定的构造(锁/易失性变量/最终字段),否则无法保证一个线程会看到另一个线程对内存所做的操作。
在这种情况下,你的保证是由锁给出的:当线程 T1 获取锁 L 时,保证它将看到线程 T2 在 T2 释放锁 L 之前对内存所做的所有修改。
在这种情况下,可以保证 T1 会看到
a
和b
的正确值,但不能保证在读取c
时会看到什么。如果您取出锁,请确保您的数据结构是线程安全的,并且如果包含的数据(即列表中的对象)不是线程安全的,请确保在每次修改和后续数据检索之间触发happens-before关系,否则会发生不好的事情。
I really don't understand if your application is single- or multi-threaded. The title says one thing, and from the body we can infer another thing. I assume that you are using more than one thread (otherwise, the question makes no sense -- why would you use synchronization between ... less than 2 threads?!).
There might be a bigger issue than performance. Visibility.
You don't give any details about the part of the code in which you
...modify a list...
, however it is very important to know the details: depending on how you've done that, if you remove the locking what might happen is: one thread modifies the list and the other thread nevers sees these modifications (or sees partial, most probably inconsistent modifications).The aspect of synchronization that it seems that you are missing is that, unless using some specific constructs (locks / volatile variables / final fields), there are no guarantees that one thread will see what another thread did to the memory.
In this case, your guarantee is given by the locks: when a thread T1 acquires a lock L, it is guaranteed that it will see all the modifications made to the memory by a thread T2 before T2 released the lock L.
In this case, it is guaranteed that T1 will see the correct values for
a
andb
, but there's no guarantee about what it will see when readingc
.If you take out your locks, be sure that your data structure is thread-safe and, if the data contained (ie, your objects inside the list) is not thread-safe, be sure that between each modification and subsequent retrieval of data you trigger a happens-before relation, otherwise bad things will happen.
我编写的测试代码显示 ReentrantLock 比单线程上的同步慢 10 倍。
由于我的自定义 TCP 协议解码器花费了 300 ns,因此锁定速度很重要。
JDK 14:
JDK 11:
我的测试:
I wrote the test code which shows me that the ReentrantLock is 10 times slower than synchronized on a single thread.
Since my decoder of a custom TCP protocol spends spends 300 ns the speed of locking matters.
JDK 14:
JDK 11:
My test: