Hi,


We are building a tool for detecting non atomic usages of concurrent
collections.



We analyzed your code using our tool and found the following behavior:



Function addColumn at class SuperColumn tries to atomically add a column to
the concurrent collection “columns_” using the following code:



IColumn oldColumn = columns_.putIfAbsent(name, column);
if (oldColumn != null)
{

IColumn reconciledColumn = reconciler.reconcile((Column)column,
(Column)oldColumn);

while (!columns_.replace(name, oldColumn, reconciledColumn))  {

oldColumn = columns_.get(name);
reconciledColumn = reconciler.reconcile((Column)column, (Column)oldColumn);

 }

}



This code can throw NullPointerException at function reconcile if there is a
columns_.remove(…) operation on the same key, by a different thread, between
the previous executed “columns_.replace(…)” and “columns_.get(…)”
operations.



Could you please let me know whether you consider this as a bug?



Another very similar scenario can occur at function “addColumn” of class
“ColumnFamily” where the program can throw NullPointerException while
checking the while loop condition.



A possible way of modifying the code for atomically adding a column to
“columns_” can be as follows:



for (;;) {

IColumn  oldColumn = columns_.get(name);



if (oldColumn == null) {

if (columns_.putIfAbsent(name, column) == null)

return;

} else {

IColumn reconciledColumn = reconciler.reconcile((Column)column,
(Column)oldColumn);



if (columns_.replace(name, oldColumn, reconciledColumn))

return;

}

}





Thanks,

Ohad

Reply via email to