Variable Volatile
:易变关键字适用于变量。Java中的volatile关键字保证了volatile变量的值将始终从主内存而不是从线程的本地缓存中读取。
Access_Modifier volatile DataType Variable_Name;
易失字段:向VM指示多个线程可能尝试同时访问/更新该字段的值。一个特殊的实例变量,必须在所有具有修改后值的线程之间共享。与Static(Class)变量类似,主内存中仅缓存了一个易失值副本,因此在执行任何ALU操作之前,每个线程必须在ALU操作之后从主内存中读取更新后的值,然后才必须写入主内存位置。(对易失性变量v的写入将与任何线程对v的所有后续后续读取进行同步),这意味着对易失性变量的更改始终对其他线程可见。
这里一个nonvoltaile variable
,如果线程T1变化T1的缓存值,线程T2不能访问更改后的值,直到T1写入,T2从主内存中读取最新修改的值,这可能会导致Data-Inconsistancy
。
volatile无法缓存-汇编器
+--------------+--------+-------------------------------------+
| Flag Name | Value | Interpretation |
+--------------+--------+-------------------------------------+
| ACC_VOLATILE | 0x0040 | Declared volatile; cannot be cached.|
+--------------+--------+-------------------------------------+
|ACC_TRANSIENT | 0x0080 | Declared transient; not written or |
| | | read by a persistent object manager.|
+--------------+--------+-------------------------------------+
Shared Variables
:可以在线程之间共享的内存称为共享内存或堆内存。所有实例字段,静态字段和数组元素都存储在堆内存中。
同步:同步适用于方法,块。一次只能在对象上执行1个线程。如果t1取得控制权,则其余线程必须等待直到它释放控制权。
例:
public class VolatileTest implements Runnable {
private static final int MegaBytes = 10241024;
private static final Object counterLock = new Object();
private static int counter = 0;
private static volatile int counter1 = 0;
private volatile int counter2 = 0;
private int counter3 = 0;
@Override
public void run() {
for (int i = 0; i < 5; i++) {
concurrentMethodWrong();
}
}
void addInstanceVolatile() {
synchronized (counterLock) {
counter2 = counter2 + 1;
System.out.println( Thread.currentThread().getName() +"\t\t « InstanceVolatile :: "+ counter2);
}
}
public void concurrentMethodWrong() {
counter = counter + 1;
System.out.println( Thread.currentThread().getName() +" « Static :: "+ counter);
sleepThread( 1/4 );
counter1 = counter1 + 1;
System.out.println( Thread.currentThread().getName() +"\t « StaticVolatile :: "+ counter1);
sleepThread( 1/4 );
addInstanceVolatile();
sleepThread( 1/4 );
counter3 = counter3 + 1;
sleepThread( 1/4 );
System.out.println( Thread.currentThread().getName() +"\t\t\t\t\t « Instance :: "+ counter3);
}
public static void main(String[] args) throws InterruptedException {
Runtime runtime = Runtime.getRuntime();
int availableProcessors = runtime.availableProcessors();
System.out.println("availableProcessors :: "+availableProcessors);
System.out.println("MAX JVM will attempt to use : "+ runtime.maxMemory() / MegaBytes );
System.out.println("JVM totalMemory also equals to initial heap size of JVM : "+ runtime.totalMemory() / MegaBytes );
System.out.println("Returns the amount of free memory in the JVM : "+ untime.freeMemory() / MegaBytes );
System.out.println(" ===== ----- ===== ");
VolatileTest volatileTest = new VolatileTest();
Thread t1 = new Thread( volatileTest );
t1.start();
Thread t2 = new Thread( volatileTest );
t2.start();
Thread t3 = new Thread( volatileTest );
t3.start();
Thread t4 = new Thread( volatileTest );
t4.start();
Thread.sleep( 10 );;
Thread optimizeation = new Thread() {
@Override public void run() {
System.out.println("Thread Start.");
Integer appendingVal = volatileTest.counter2 + volatileTest.counter2 + volatileTest.counter2;
System.out.println("End of Thread." + appendingVal);
}
};
optimizeation.start();
}
public void sleepThread( long sec ) {
try {
Thread.sleep( sec * 1000 );
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
静态[ Class Field
]与挥发性[ Instance Field
]-两者都不被线程缓存
@看到