我們的想法是用key自身的class
型別作為key。因為class
是引數化的型別,它可以確保我們使context方法是型別安全的,而無需訴諸於乙個未經檢查的強制轉換為t
。這種形式的乙個class
物件稱之為型別令牌(type token)。
public class context
public t get( classkey )
[...]
}
請注意在context#get
的實現中是如何用乙個有效的動態變數替換向下轉型的。客戶端可以這樣使用這個context:
context context = new context();
runnable runnable ...
context.put( runnable.class, runnable );
// several computation cycles later...
executor executor = ...
context.put( executor.class, executor );
// even more computation cycles later...
runnable value = context.get( runnable.class );
這次客戶端的**將可以正常工作,不再有類轉換的問題,因為不可能通過乙個不同的值型別來交換某個鍵值對。
bloch指出這種模式有兩個侷限性。「首先,惡意的客戶端可以通過以原生態形式(raw form)使用class物件輕鬆地破壞型別安全。」為了確保在執行時型別安全可以在context#put
中使用動態轉換(dynamic cast)。
public void put( classkey, t value )
第二個侷限在於它不能用在不可具體化(
non-reifiable )的型別中
換句話說,你可以儲存runnable
或runnable
,但是不能儲存list
。
這是因為list
沒有特定class物件,所有的引數化型別指的是相同的list.class
物件。因此,bloch指出對於這種侷限性沒有滿意的解決方案。
為了能夠儲存多條同型別容器條目,我們可以用自定義key改變context
類。這種key必須提供我們型別安全所需的型別資訊,以及區分不同的值物件(value objects)的標識。乙個以string
例項為標識的、幼稚的key實現可能是這樣的:
public class key
}
我們再次使用引數化的class
作為型別資訊的鉤子,調整後的context將使用引數化的key
而不是class
。
public class context
public t get( keykey )
[...]
}
客戶端將這樣使用這個版本的context
:
context context = new context();
runnable runnable1 = ...
keykey1 = new key<>( "id1", runnable.class );
context.put( key1, runnable1 );
runnable runnable2 = ...
keykey2 = new key<>( "id2", runnable.class );
context.put( key2, runnable2 );
// several computation cycles later...
runnable actual = context.get( key1 );
assertthat( actual ).issameas( runnable1 );
雖然這個**片段可用,但仍有缺陷。在context#get
中,key
被用作查詢引數。用相同的identifier和class初始化兩個不同的key
的例項,乙個用於put,另乙個用於get,最後get
操作將返回null
。這不是我們想要的……context context = new context();
runnable runnable1 = ...
keykey1 = new key<>( "same-id", runnable.class );
keykey2 = new key<>( "same-id", runnable.class );
context.put( key1, runnable1 );//乙個用於put
context.get(key2); //另乙個用於get --> return null;
幸運的是,為key
設計合適的equals
和hashcode
可以輕鬆解決這個問題,進而使hashmap
查詢按預期工作。最後,你可以為建立key提供乙個工廠方法以簡化其建立過程(與static import一起使用時有用):
public static key key( string identifier, class type )
STL容器的執行緒安全?
執行緒安全的情況 執行緒不安全的情況 看到風險了吧?在工程中多執行緒操作stl的場景應該還是比較常見的,乙個典型的例子就是用其來做生產者 消費者模型的佇列或者其他共享佇列,這樣為了應對執行緒安全問題我們必須自己對容器操作進行封裝。這是我自己實現的的封裝類threadsafe container.h,...
docker容器的安全加固
社群中常用的做法是利用lxcfs來提供容器中的資源可見性。lxcfs是乙個開源的fuse 使用者態檔案系統 實現來支援lxc容器。lxcfs通過使用者態檔案系統,在容器中提供下列 procfs 的檔案 proc cpuinfo proc diskstats proc meminfo proc sta...
docker容器的安全加固
社群中常用的做法是利用lxcfs來提供容器中的資源可見性。lxcfs是乙個開源的fuse 使用者態檔案系統 實現來支援lxc容器。lxcfs通過使用者態檔案系統,在容器中提供下列 procfs 的檔案 proc cpuinfo proc diskstats proc meminfo proc sta...