简体   繁体   English

Objective C相当于java中的intern()

[英]Objective C equivalent of intern() in java

I got to implement some synchronization algorithms depending on strings. 我必须根据字符串实现一些同步算法。 I mean two threads have to be synchronized and the pair of threads both depend on a string value (one pair of threads for String A, one pair for String B, and so on). 我的意思是必须同步两个线程,并且这对线程都依赖于字符串值(字符串A的一对线程,字符串B的一对线程,依此类推)。

In java, I could implement the algorithm using the method intern to get a single lock object that is shared by both threads. 在java中,我可以使用方法实现来实现算法,以获得由两个线程共享的单个锁对象。 Java pulls all litteral in a jvm built-in pool and interne allows to transform any string created dynamically into a litteral in the pool. Java在jvm内置池中提取所有内容,并且interne允许将动态创建的任何字符串转换为池中的litteral。

I understood that there is also a pooling mechanism in Objective C . 我知道目标C中还有一个池化机制

But is there any equivalent to intern() in Java, ie a way to transform a normal String into a litteral String from the pool of String constants. 但是在Java中是否存在与intern()的等价物,即从String常量池中将普通String转换为litteral String的方法。 To get the reference to this unique String litteral so that both my threads could get synchronize on the same object. 获取对这个唯一的String postteral的引用,以便我的两个线程可以在同一个对象上进行同步。

I know there are some work around but they all imply a lot of String comparisons that I would like to avoid. 我知道有一些工作,但它们都暗示了我想避免的很多字符串比较。 (Although I believe intern does it but in an optimized way...) (虽然我相信实习生是以优化的方式做到的......)

To explain my problem in more general term : I want to avoid having a Dictionnary that maps a String to a lock. 用更一般的术语来解释我的问题:我想避免使用将字符串映射到锁的字典。 Java allows me to do that thanks to intern as the String litteral (pooled) will become the lock. Java允许我这样做,这要归功于实习生,因为String litteral(pooled)将成为锁定。 Is there any equivalent or must I use this map. 有没有等价物或者我必须使用这张地图。

Thanks folks, Stéphane 谢谢大家,Stéphane

I program regularly in both Java and Objective-C. 我经常在Java和Objective-C中编程。

First, what you describe seems a less-than-ideal way to share a lock. 首先,您描述的内容似乎是一种不太理想的共享锁定方式。 It's tricky, it's brittle, and it will confuse other coders not so intimate with how String interning works. 它很棘手,很脆弱,而且会让其他编码人员对String实习的工作方式感到困惑。 Why not just have a lock object in one class exposed to the other as a constant? 为什么不将一个类中的锁定对象作为常量暴露给另一个类?

public class Foobar {

    public static final Object LOCK = new Object();

    public void doLockedStuff() {
        synchronized (LOCK) {
            // code here
        }
    }

}

public class Barfoo {
    public void doLockedStuff() {
        synchronized (Foobar.LOCK) {
            // code here
        }
    }
}

And then you can adopt a similar approach in Objective-C - a class method exposing a shared LOCK object. 然后,您可以在Objective-C中采用类似的方法 - 一种暴露共享LOCK对象的类方法。

I think mapping the strings to the locks they represent is your best bet. 我认为将字符串映射到它们代表的锁是最好的选择。

You don't want to lock on the String itself (or an interned version) because it's a shared object in the JVM. 您不希望锁定String本身(或实例版本),因为它是JVM中的共享对象。 You don't know if another component in the JVM is doing the same thing, which could cause a deadlock. 您不知道JVM中的另一个组件是否正在执行相同的操作,这可能会导致死锁。

Java Concurrency in Practice describes this better, but I can't find a reference at the moment. Java Concurrency in Practice更好地描述了这一点,但我目前找不到引用。

The map containing your locks won't incur a large performance problem if you use a HashMap because Strings are immutable and the hash code of the String will likely only have to be calculated once. 如果使用HashMap,包含锁的映射不会产生大的性能问题,因为字符串是不可变的,并且字符串的哈希码可能只需要计算一次。

I finally used a dictionnary that binds every string to a conditionnal lock. 我终于使用了一个字典,它将每个字符串绑定到一个条件锁。

Thanks all 谢谢大家

Without suggesting that is the best way to generate the locks that you are looking for but here is a little hack to give you the effect you want: 没有暗示这是生成你正在寻找的锁的最佳方法,但这里有一点点黑客可以给你想要的效果:

NSString *stringA = [NSString stringWithString:@"Hello"];
NSString *stringB = [NSString stringWithFormat:@"%@l%@",@"Hel",@"o"];
NSString *stringC = [NSString stringWithFormat:@"Hell%@", @"o"];

NSLog(@"%p / %p / %p", stringA, stringB, stringC);

NSNumber *lockA = [NSNumber numberWithUnsignedInteger:stringA.hash];
NSNumber *lockB = [NSNumber numberWithUnsignedInteger:stringB.hash];
NSNumber *lockC = [NSNumber numberWithUnsignedInteger:stringC.hash];

NSLog(@"%p / %p / %p", lockA, lockB, lockC);

You will notice that eventhough the strings have different addresses, their corresponding NSNumbers don't. 您会注意到尽管字符串具有不同的地址,但它们相应的NSNumber却没有。 That's because NSNumbers for a given number is a singleton. 那是因为给定数字的NSNumbers是单身。

You can now use @synchronize() on these "lock" objects. 您现在可以对这些“锁定”对象使用@synchronize()

-- Edit -- - 编辑 -

The fact that NSNumbers are singletons for a given value is an internal detail to the implementation, which is one reason why it might be a good idea to shop around for a real locking mechanism such as a dictionary indexed by NSString for example. NSNumbers对于给定值是单例的事实是实现的内部细节,这是为什么可以选择真正的锁定机制(例如由NSString索引的字典)的一个原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM