问题
From other questions, I learned that the elements of a volatile array are not volatile. Only the reference itself is volatile.
volatile[] int data;
Thread A: data[4] = 457;
Thread B: System.out.println(data[4]);
Here, Thread B might never see the updated value.
Which options/alternatives do I have to achieve the same thing? I would like to avoid having to synchronize the array, since it is hardly ever altered. However, it is being read a lot by some threads. Synchronizing it will very likely lower the throughput, which is very important in this example.
Is my only option a copy-on-write data-structure here? That is, copying the array into a new array and update the array reference afterwards.
Are there any other options? I read somewhere that encapsulating the array into a class (with only one member, the array) achieves the same thing, but I doubt that is true. I cannot see how that might help.
Please note that my target JVM is 1.4. This means I cannot use the java.util.concurrent
package.
-------------- edit edit edit --------------
In Java volatile array? I read that re-assigning the array reference achieves the volatility semantics. This should give the correct results:
volatile[] int data;
Thread A: data[4] = 457;
Thread A: data = data;
Thread B: System.out.println(data[4]);
Is this valid on older JVMs?
回答1:
An array is marked volatile, that is only the reference is marked as volatile. The elements of array itself do not inherit the memory visibility semantics of the volatile keyword at all.
What I can suggest build a AtomicIntergerArray
class in your own. Where you can keep a final int[] data
refernece and synchronize it properly.
Also take a look on AtomicIntergerArray
implementation code.
Or else you can use Backport api's AtomicIntegerArray.
This project is to provide a concurrency library that works with uncompromised performance on all Java platforms currently in use, allowing development of fully portable concurrent applications. More precisely, the traget scope is Java 1.3 and above, and some limited support if offered for Java 1.2.
回答2:
Just use wrapper:
class VolatileInt{
volatile int value;
}
VolatileInt[] create(int size){
VolatileInt[] array = new VolatileInt[size];
for(int k=0;k<size;k++)
array[k]=new VolatileInt();
return array;
}
VolatileInt[] array = create(10);
回答3:
Using arr=arr
manages Java to rewrite the storage address of the array (arrays are also objects in Java). The array fields arr[i]
do not gain the volatile property.
In some cases, arr=arr
might work for unknown reasons, but it does not bring you to the safe side.
If you want to stay safe, use the Atomic*Array
stuff. Yes, the extra atomicity is costly, but I guess if you consider access times and storage footprint it is better than linked structures.
If you want to avoid global locks, you may consider to split the array into subsets. This makes locks affect only a subset and you still keep the volatility for all values.
I share your problem, by best bet are Atomic*Arrays
.
来源:https://stackoverflow.com/questions/15739942/alternatives-for-volatile-array