通过上面结果可以看出此时synchronized 可以锁住字符串了,由此可以得出我们日常中如果通过锁字符串对象的方式是锁不住字符串。因此字符串对象不是同一个地址,因此如果想要锁住用户ID,需要把用户ID添加到字符串常量池中。如果通过User user = new User()的方式锁user.getUserId()是无法有效锁住用户的。
看下下面的例子:
1 2 3 4 5 6 7 8
publicstaticvoidmain(String[] args){ String name = "a"; String nameObj = new String("a");
@Override public E intern(E sample){ while (true) { // trying to read the canonical... InternalEntry<E, Dummy, ?> entry = map.getEntry(sample); if (entry != null) { E canonical = entry.getKey(); if (canonical != null) { // only matters if weak/soft keys are used return canonical; } }
// didn't see it, trying to put it instead... Dummy sneaky = map.putIfAbsent(sample, Dummy.VALUE); if (sneaky == null) { return sample; } else { /* Someone beat us to it! Trying again... * * Technically this loop not guaranteed to terminate, so theoretically (extremely * unlikely) this thread might starve, but even then, there is always going to be another * thread doing progress here. */ } } } }
主要看下 putIfAbsent方法:
1 2 3 4 5 6 7 8
@CanIgnoreReturnValue @Override public V putIfAbsent(K key, V value){ checkNotNull(key); checkNotNull(value); int hash = hash(key); return segmentFor(hash).put(key, hash, value, true); }
/** * Instructs the {@link InternerBuilder} to build a strong interner. * * @see Interners#newStrongInterner() */ public InternerBuilder strong(){ this.strong = true; returnthis; }
/** * Instructs the {@link InternerBuilder} to build a weak interner. * * @see Interners#newWeakInterner() */ @GwtIncompatible("java.lang.ref.WeakReference") public InternerBuilder weak(){ this.strong = false; returnthis; }
/** * Sets the concurrency level that will be used by the to-be-built {@link Interner}. * * @see MapMaker#concurrencyLevel(int) */ public InternerBuilder concurrencyLevel(int concurrencyLevel){ this.mapMaker.concurrencyLevel(concurrencyLevel); returnthis; }
public <E> Interner<E> build(){ if (!strong) { mapMaker.weakKeys(); } returnnew InternerImpl<E>(mapMaker); } }