您当前的位置:首页 > 计算机 > 编程开发 > Java

Java volatile 的内存语义

时间:12-14来源:作者:点击数:

非 volatile 变量

public class volatileTest {
/*
将代码改成如下,再执行:
static volatile ArrayList<Integer> list = new ArrayList<Integer>();
线程不再死循环,因为读取list.size会触发线程刷新工作内存,可以看到,即使b、i、
str没有设置成volatile变量,仍然会一起刷新过来。
用volatile修饰b、i、str、list任何一个都能起到刷新工作内存的效果。
*/
 static boolean b = false;
 static int i =1;
 static String str ="1";
 static ArrayList<Integer> list = new ArrayList<Integer>();
 public static void main(String[] arg) throws Exception {
 Thread t = new Thread(new Runnable() {
 public void run() {
 printf(String.format("[%s] _start_ b=%s i=%d str=%s",
 Thread.currentThread().getName(), b,i,str));
 /*等待list 、b 、I、 str中任何一个变
化,都会跳出这个循环*/
 while(list.size() == 0 && !b && i==1 && str.equals("1"));
 printf (String.format("[%s] _end_ b=%s i=%d str=%s",
 Thread.currentThread().getName(), b,i,str));
 }
 });
 t.start();
 Thread.sleep(1000);
 /*改变他们的值*/
 list.add(new Integer(1));
 b=true;i=2;str="2";
 printf (String.format("main end b=%s i=%d str=%s", b,i,str));
 }
}

运行结果:线程进入死循环,因为线程不会主动去读取主内存中的值。

synchronized 的内存语义

JMM 对 synchronized 也实现了同样的语义保证:

获取锁:将线程工作内存区域中的共享变量设置成无效,必须从主内存重新获取。

释放锁:将工作内存中的数据刷新到主内存。

public class volatileTest {
 static boolean b = false;
 static int i =1;
 static String str ="1";
 static ArrayList<Integer> list = new ArrayList<Integer>();
 public static void main(String[] arg) throws Exception {
 Thread t = new Thread(new Runnable() {
 public void run() {
 printf(String.format("[%s] _start_ b=%s i=%d str=%s",
 Thread.currentThread().getName(), b,i,str));
 while(list.size() == 0 && !b && i==1 && str.equals("1"))
 {
 // b 、i、str、list 虽然都没有设置成 volatile,这里的 synchronized 具有保持工作内存与主内存一致性的效果。
 synchronized (this){}
 /*
 隐藏的锁
System.out.println()
public void println(String x) {
 synchronized (this) {
 print(x);
 newLine();
}
}
*/
 System.out.println("")
 }
 printf(String.format("[%s] _end_ b=%s i=%d str=%s",
 Thread.currentThread().getName(), b,i,str));
 }
 });
 t.start();
 Thread.sleep(1000);
 list.add(new Integer(1));
 b=true;i=2;str="2";
 printf(String.format("main end b=%s i=%d str=%s", b,i,str));
 }
}

线程等待-恢复的内存语义

线程等待-恢复,恢复时会重新加载主内存:

线程休眠

Thread.currentThread().sleep(1);

线程暂停

Thread.currentThread().suspend(); 

可重入锁

reentrantLock.lock();
reentrantLock.unlock();
readWritelock.readLock().lock(); //读锁
readWritelock.readLock().unlock();
readWritelock.writeLock().lock();//写锁
readWritelock.writeLock().unlock();

循环屏障等待

try{barrier.await();}catch (Exception e){} 

交换器等待交换

try{exchanger.exchange(1);}catch (Exception e){}

语义锁

synchronized (lockObject) {
 try { lockObject.wait();}catch (Exception e){}
}

LockSupport 的阻塞-恢复:

LockSupport.parkNanos(1);
LockSupport.park();

CountDownLatch 的 await 等待-恢复:

try{ latch.await(); }catch (Exception e){ } 

public class volatileTest {
static boolean b = false;
static int i =1;
static String str ="1";
static ArrayList<Integer> list = new ArrayList<Integer>();
public static void main(String[] arg) throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
final CyclicBarrier barrier = new CyclicBarrier(2);
final Exchanger exchanger = new Exchanger();
final Object lockObject = new Object();
Thread t = new Thread(new Runnable() {
public void run() {
printf(String.format("[%s] _start_ b=%s i=%d str=%s",
Thread.currentThread().getName(), b,i,str));
while(list.size() == 0 && !b && i==1 && str.equals("1"))
{
try{Thread.sleep(1);}catch (Exception e){}
}
printf(String.format("[%s] _end_ b=%s i=%d str=%s",
Thread.currentThread().getName(), b,i,str));
}
});
t.start();Thread.sleep(1000);
list.add(new Integer(1));b=true;i=2;str="2";
printf(String.format("main end b=%s i=%d str=%s", b,i,str));
}
}
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐