同步死锁(String intern())
我用户sun jdk 1.5 ThreadPoolExecutor( 24, 24,60,TimeUnit.SECONDS, new LinkedBlockingQueue())。 有时我使用jdb工具发现线程池中所有线程的状态都是“在监视器中等待”,代码是:
String key = getKey(dt.getPrefix(), id);
synchronized (key.intern()) { ----->
“synchronized(key.intern())”是否有问题?
我使用jdb工具得到以下信息,24个线程的状态是“在监视器中等待”,这意味着24个线程在“key.intern()”处死锁。
(java.lang.Thread)0x28 pool-3-thread-2 在监视器中等待
(java.lang.Thread)0x27 pool-3-thread-3 在监视器中等待
(java.lang.Thread)0x1b pool-3- thread-4 在监视器中等待
(java.lang.Thread)0x1a pool-3-thread-5 在监视器中等待
(java.lang.Thread)0x19 pool-3-thread-6 在监视器中等待
(java.lang. Thread)0x18 pool-3-thread-7 在监视器中等待
(java.lang.Thread)0x17 pool-3-thread-8 在监视器中等待 ...
所以结果是:在多线程环境下,Sting intern()方法可能会死锁,好吗?
I user sun jdk 1.5 ThreadPoolExecutor( 24, 24,60,TimeUnit.SECONDS, new LinkedBlockingQueue()). soemtime I use jdb tool to find the status of all threads in thread pool are " waiting in a monitor", the code is :
String key = getKey(dt.getPrefix(), id);
synchronized (key.intern()) { ----->
Is there a problem in "synchronized (key.intern()) " ?
I get following informatnio using jdb tool, the status of 24 threads is "waiting in a monitor", it means 24 threads are deadlock at "key.intern()".
(java.lang.Thread)0x28 pool-3-thread-2 waiting in a monitor
(java.lang.Thread)0x27 pool-3-thread-3 waiting in a monitor
(java.lang.Thread)0x1b pool-3-thread-4 waiting in a monitor
(java.lang.Thread)0x1a pool-3-thread-5 waiting in a monitor
(java.lang.Thread)0x19 pool-3-thread-6 waiting in a monitor
(java.lang.Thread)0x18 pool-3-thread-7 waiting in a monitor
(java.lang.Thread)0x17 pool-3-thread-8 waiting in a monitor
...
so the result is : in multi-threads environment, Sting intern() method may be deadlock, ok ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
相当。 问题是 key.intern() 并不是那么唯一,因为它从池中返回一个字符串。 即使在不同的对象上使用 String.intern() 也可能返回相同的对象。 尝试使用
key
本身或完全不同的对象。Quite. The problem is that key.intern() isn’t really that unique because it’s returning a string from a pool. String.intern() might return the same object even when used on different objects. Try using
key
itself or a different object altogether.我曾经发布过一个与此相关的问题,您可能想看一下:问题在 String 对象上同步?
我学到的是:使用 intern'ed Strings 进行同步是一种不好的做法。
I posted a related question to this once that you might want to take a look at: Problem with synchronizing on String objects?
What I learned was: using intern'ed Strings for synchronization is a bad practice.
该代码几乎肯定会尝试同步影响同一键的操作。 因此,它调用 intern() 来确保相同的键映射到相同的对象,因此作为同步对象是有效的。
问题是,如果您在那里遇到瓶颈(这不是死锁),则问题是您使用同一密钥同时进行了太多操作。
重新考虑需要同步的内容。
The code is almost certainly trying to synchronize actions that affect the same key. So it's calling intern() to ensure that the same key gets mapped to the same object, and therefore is valid as an object for synchronization.
The problem, if you're running into a bottleneck there (it's not a deadlock) is that you have too many operations coming in at the same time using the same key.
Rethink what needs to be synchronized.
如果您需要在字符串上进行同步,请不要使用字符串实例作为互斥体(无论是否内部)。 不过,可以使用字符串来创建良好的互斥对象: 正在同步 ID。
If you need to synchronize on a String, don't use a String instance as the mutex (interned or not). A string can be used to create a good mutex object, though: synchronizing on an ID.
你有两个问题。
一种是使用 String 作为锁。 第二个是僵局。
如果您使用 String 作为锁,您将失去对“谁”和“哪里”将获取该对象锁的控制。
您的死锁问题可能是由 String 上的锁定引起的,也可能不是。 然而,死锁的实际原因是:“你的代码可能导致死锁。”。 如果它能发生,它就会发生。
您必须跟踪线程的堆栈来解决死锁。
You are having two problems.
The one is using String as the lock. The second one is deadlock.
If you using String as lock, you will lose the control of "who" and "where" will take that object lock.
Your deadlock issue, which may or may not caused by lock on String. However, the actual reason of deadlock is: "Your code can lead deadlock.". If it can happen, it will happen.
You must trace your threads' stacks to resolve deadlocks.
这里没有足够的代码来说明出了什么问题。 正如前面提到的,这可能是一个瓶颈,但至少应该有一个线程正在运行(CPU 使用率相当高)才能发生这种情况,或者拥有锁的线程将进入睡眠状态而不释放锁。
死锁是另一种可能性,但这需要在多个线程上的两个单独的锁上进行同步,并且您在此处仅显示了一个锁对象。
如果没有更多信息,确实无法确定。
There is not enough code here to tell what is going wrong. It could be a bottleneck as has been mentioned, but at least one thread should be running (with fairly heavy CPU usage) for that to happen, or a thread that has the lock is put to sleep without releasing the lock.
A deadlock is another possibility but that would require synchronization on two separate locks on multiple threads, and you have shown only one lock object here.
It is really impossible to determine without more information.
正如 Bombe 所说, key.intern() 不一定会给你一个非常独特的密钥来同步。
但是,您应该谨慎更改代码。 在更改代码之前,您需要了解代码中的锁定策略。 删除 intern() 调用可能会给您提供看起来工作正常的代码,但其中包含稍后会困扰您的数据争用。
As Bombe says, key.intern() won't necessarily give you a very unique key to synchronize on.
You should be cautious about changing the code, however. You need to understand the locking strategy in the code before changing it. Removing the intern() call may give you code that appears to work correctly but contains a data race that will bite you later.
你很可能陷入僵局。
如果要避免死锁,每个线程必须始终以相同的顺序获取锁。 当您使用 String.intern() 获取锁时,您将锁定整个 JVM 中的任何代码都可以访问并锁定的实例。 最有可能的是,您自己的代码中的其他线程陷入了死锁,但事实并非如此。
我不确定你的回答中“key.intern() 保证唯一性”是什么意思。
intern()
方法通过为每个等效字符串返回相同的对象来减少唯一性。上面的代码将证明,即使您创建了两个唯一的实例,通过实习它们,您也可以将它们替换为单个规范实例。
每当您使用在您自己的代码之外可见的对象作为锁时,都会存在危险。 尝试坚持使用私有成员、不允许从自己的堆栈中逃逸的对象等。
You very likely have a deadlock.
If you want to avoid deadlocks, every thread must always acquire locks in the same order. When you use String.intern() to get your locks, you are locking on an instance that any code in the entire JVM has access to, and lock on. Most likely, other threads in your own code are deadlocking, but it doesn't have to be.
I'm not sure what you mean in your answer by "key.intern() guarantee uniqueness". The
intern()
method reduces uniqueness by returning the same object for every string that's equivalent.The code above will demonstrate that even though you created two unique instances, by interning them, you replaced them with a single, canonical instance.
There's danger any time you use an object that's visible outside your own code as a lock. Try to stick to private members, objects that you don't allow to escape from your own stack, etc.
如何使用带有锁定值的唯一字符串前缀并在同步块中使用 String.intern() 。 例如,如果要锁定字符串“lock1”,请使用如下 UUID 前缀:“85e565b3-d440-46e7-93b6-69ee7e9a63ee-lock1”。 这种类型的字符串不应已存在于实习池中。 即其他代码造成死锁的可能性非常低。
How about using a unique string prefix with the locking value and using the String.intern() in the synchronized block. For example if you want to lock on the string "lock1", use a UUID prefix like this: "85e565b3-d440-46e7-93b6-69ee7e9a63ee-lock1". This type of string should not be already in the intern pool. i.e. chance of deadlock by other code is very low.
key.intern() 保证唯一性,因为 key.intern() 从字符串常量池返回一个字符串。
http://java.lang. sun.com/j2se/1.4.2/docs/api/java/lang/String.html#intern()
实习生
公共字符串实习生()
返回字符串对象的规范表示。
字符串池最初是空的,由 String 类私有维护。
key.intern() guarantee uniqueness because key.intern() returns a string from String constants pool.
http://java.sun.com/j2se/1.4.2/docs/api/java/lang/String.html#intern()
intern
public String intern()
Returns a canonical representation for the string object.
A pool of strings, initially empty, is maintained privately by the class String.
String.intern() 是一种本机方法 - 这可能是问题的原因。
String.intern() is a native method - that might be a cause of the problem.