多个线程同时访问 synchronized(this) 同步代码块或 synchronized 方法时,一个时间内只能有一个线程得到执行。
另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
public class SyncFunction {
public void Print(String str) throws Exception {
System.out.println(str + " begin");
Thread.sleep(2000);
System.out.println(str + " end");
}
// 因为同步方法和同步代码块都是锁 this 对象。两个线程会以线程安全的方式顺序互斥执行
public synchronized void syncfun_1() throws Exception {
Print("syncfun_1");
}
/*
锁定当前对象,相当于this
*/
public void syncfun_2() throws Exception{
synchronized (this){
Print("syncfun_2");
}
}
public static void main(String[] arg) throws Exception {
final SyncFunction syncfun = new SyncFunction();
new Thread(new Runnable() {
public void run() {
try{syncfun.syncfun_1();}catch (Exception e){}
}
}).start();
new Thread(new Runnable() {
public void run() {
try{syncfun.syncfun_2();}catch (Exception e){}
}
}).start();
}
}
public class SyncFunction {
public static void Print(String str) throws Exception {
System.out.println(str + “ begin”);
Thread.sleep(2000);
System.out.println(str + “ end”);
}
/*
1.syncfun_1和syncfun_2以线程安全方式顺序互斥执行。
2.静态方法和静态代码块都是锁住对应的类class
*/
public static synchronized void syncfun_1() throws Exception{
Print(“syncfun_1”);
}
public static void syncfun_2() throws Exception {
synchronized (SyncFunction.class)
{
Print(“syncfun_2”);
}
}
public static void main(String[] arg) throws Exception {
new Thread(new Runnable() {
public void run() {
try{SyncFunction.syncfun_1();}catch (Exception e){}
}
}).start();
new Thread(new Runnable() {
public void run() {
try{SyncFunction.syncfun_2();}catch (Exception e){}
}
}).start();
}
}
假设主内存中存在一个 boolean 类型的变量b,当在线程内部去访问 b 的时候,可能访问的是线程工作内存中的变量 b 的拷贝 _b,并不是访问的主内存中的 b,为了确保 b 和 _b 保持一致性,线程内部的工作内存和主内存必须存在交互机制,以保障在线程内部工作内存是主内存的一份最新的拷贝,即变量对所有线程具有可见性。
java 线程 <----------> 工作内存 <--------> save
java 线程 <----------> 工作内存 <--------> 和 <--------->主内存
java 线程 <----------> 工作内存 <--------> load 操作
读 volatile 变量:会将主内存拷贝到工作内存
写 volatile 变量:会将工作内存拷贝到主内存
上面是 JMM 对程序员建立的内存模型,程序员可以按照上面的模型去理解。实际上,线程内部根本不存在工作内存,JMM 实际上对 volatile 变量的处理是通过禁止一些列重排序,进而达到上面的内存语义。

