从字符串创建对象并在同步块中用作监视器
Creating an object from string and using as monitor in synchronized block
我在某些 classes 上使用注释,通过反射我得到了注释的一些字符串,它对于每个 class.
都是唯一的
我正在考虑使用该字符串来同步代码块,但我只想在注释字符串值相同时阻止代码访问,如果字符串不相同则另一个线程可以进入执行其任务.我知道不能直接用string,int也没有monitor所以不能直接用hashcode。当我使用 jMeter 加载测试这段代码时,这种方式会产生任何问题吗?
public class LockObject {
private String lockString;
public LockObject(String lockString) {
this.lockString = lockString;
}
public int hashCode() {
returns hashcode for string;
}
@Override
public boolean equals(Object obj) {
}
}
public class TestClass {
public void someMethod() {
String annotationString = "fetchedByAnnotation that i use on some class by reflection";
//what i want if string is same then second thread won't enter this block
synchronized (new LockObject(annotationString)) {
//some task based on that string
}
}
}
I know that I can't use string directly and ints don't have monitor so
I can't use hashcode directly.
是的,尽管如此,您可以(但您不应该)利用方法 intern(). From source 人们可以阅读:
The java string intern() method returns the interned string. It
returns the canonical representation of string.
It can be used to return string from memory, if it is created by new
keyword. It creates exact copy of heap string object in string
constant pool.
String annotationString = // ...;
synchronized (annotationString.intern())
尽管如此,锁定字符串的问题在于其他对象可能出于完全不同的目的无意中锁定了这些相同的字符串。换句话说,字符串具有全局语义范围,您无法控制,即确保这些相同的字符串不会在其他地方用作锁定机制。从这个SO Thread(以及其他要点)可以读到:
Locking on strings is discouraged, the main reason is that (because of
string-interning) some other code could lock on the same string
instance without you knowing this. Creating a potential for deadlock
situations.
Now this is probably a far fetched scenario in most concrete
situations. It's more a general rule for libraries.
另一种解决方案是使用 <String, Object>
的 Map
,其中 key
是从注释中读取的字符串,而 value
是一个对象哪些线程可以用来同步。
Map
将在线程之间共享,因此在访问这样的 Map
时必须确保 mutual exclusion。每次线程从注释中读取字符串时,如果尚未添加,则将该字符串添加到 Map
,否则在与该字符串 key
.
关联的 value
上同步
我在某些 classes 上使用注释,通过反射我得到了注释的一些字符串,它对于每个 class.
都是唯一的我正在考虑使用该字符串来同步代码块,但我只想在注释字符串值相同时阻止代码访问,如果字符串不相同则另一个线程可以进入执行其任务.我知道不能直接用string,int也没有monitor所以不能直接用hashcode。当我使用 jMeter 加载测试这段代码时,这种方式会产生任何问题吗?
public class LockObject {
private String lockString;
public LockObject(String lockString) {
this.lockString = lockString;
}
public int hashCode() {
returns hashcode for string;
}
@Override
public boolean equals(Object obj) {
}
}
public class TestClass {
public void someMethod() {
String annotationString = "fetchedByAnnotation that i use on some class by reflection";
//what i want if string is same then second thread won't enter this block
synchronized (new LockObject(annotationString)) {
//some task based on that string
}
}
}
I know that I can't use string directly and ints don't have monitor so I can't use hashcode directly.
是的,尽管如此,您可以(但您不应该)利用方法 intern(). From source 人们可以阅读:
The java string intern() method returns the interned string. It returns the canonical representation of string.
It can be used to return string from memory, if it is created by new keyword. It creates exact copy of heap string object in string constant pool.
String annotationString = // ...;
synchronized (annotationString.intern())
尽管如此,锁定字符串的问题在于其他对象可能出于完全不同的目的无意中锁定了这些相同的字符串。换句话说,字符串具有全局语义范围,您无法控制,即确保这些相同的字符串不会在其他地方用作锁定机制。从这个SO Thread(以及其他要点)可以读到:
Locking on strings is discouraged, the main reason is that (because of string-interning) some other code could lock on the same string instance without you knowing this. Creating a potential for deadlock situations.
Now this is probably a far fetched scenario in most concrete situations. It's more a general rule for libraries.
另一种解决方案是使用 <String, Object>
的 Map
,其中 key
是从注释中读取的字符串,而 value
是一个对象哪些线程可以用来同步。
Map
将在线程之间共享,因此在访问这样的 Map
时必须确保 mutual exclusion。每次线程从注释中读取字符串时,如果尚未添加,则将该字符串添加到 Map
,否则在与该字符串 key
.
value
上同步