史上最全synchronized用法详解
2017-05-11 18:00
465 查看
Java中synchronized关键字用于代码的同步执行,他可以修饰代码块、方法、this、Object.class,能够保证在多线程环境中只有线程执行。synchronized作用范围越小并发能力越强,下面我们就各种场景来详解举例说明。
两个线程类
启动线程类
运行结果,ThreadA运行完成之后ThreadB才能继续执行
class SynchronizedThis一个synchronized(this)同步代码块一个synchronized方法
两个线程类和启动线程类同上
运行结果,线程A运行完成之后线程B才可以运行
两个线程类和启动线程类同上
运行结果,线程A和线程B并发一起执行了
两个线程类
启动线程类
同一个SynchronizedThis
运行结果,线程B需要等待线程A运行完成之后才执行
多个SynchronizedThis
运行结果,由于锁定的对象不是同一个所以可以并发执行,不会阻塞,
这边需要注意的是如果synchronized(字符常量),无论new多少个对象都会阻塞不会并发执行,因为JVM维护了一个String,Integer等常量池,new新的对象他不会创建新的字符串,而是引用字符串常量池中已经存在的字符串。
注:synchronized(obj)obj不能是基本数据类型,可以包装数据类型
例如:
运行结果
上面的private String flag = new String();是个全局变量,如果我们改成局部变量,即使我们只new一个对象,也会并发执行,因为JVM会为每个线程分配一个私有的空间,TheadA和TheadB两个线程锁定的不是同一个flag,下面让我们来验证下:
线程类同上,直接看启动线程类
运行结果,A和B并发执行了
两个线程类:
启动线程类
运行结果,线程A和线程B可以并发异步执行,因为他们锁的对象不是一个,一个是flag,一个是当前实例this
两个线程类,线程启动类同上
运行结果,线程B需要等待线程A执行完成之后再执行,这是因为synchronized方法和synchronized(this)效果一样,都是锁定当前this
两个线程类
线程启动类
运行结果,线程A和线程B可以并发异步执行,他们一个锁的是this一个当前对象class
两个线程类和线程启动类同上
运行结果,线程B需要等待线程A运行完成之后才能运行,因为静态静态方法添加synchronized之后锁定的是当前类.class
线程启动类,我new一个对象
运行结果,线程B需要等待线程A执行完之后才能执行
如果new两个对象
运行结果,和new一个对象效果一样,说明synchronized(SynchronizedThis.class)是对JVM中所有对象实例加锁,后面我再写一篇文章介绍下synchronized在JVM中是怎么工作的
总结(这里的同一个对象是指我上面的SynchronizedThis sthis = new SynchronizedThis();new了一个还是两个):
1、多个synchronized(this)
同一个对象:不能并发执行,不同对象:可以并发
2、synchronized(this)代码块与synchronized方法
同一个对象::两个加锁效果一样,不能并发执行;不同对象:可以并发
3、synchronized(任意对象)与synchronized方法
同一个对象:可以并发,不同对象:可以并发
4、多个synchronized方法
同一个对象:不能并发执行,不同对象:可以并发
5、synchronized方法与synchronized(*.class)
同一个对象:可以并发,不同对象:可以并发
6、静态synchronized方法与synchronized(*.class)
同一个对象:不能并发执行,不同对象:不能并发执行
7、synchronized(*.class)之间
同一个对象:不能并发执行,不同对象:不能并发执行
下篇文章我会对synchronized在JVM中怎么工作的进行详细讲解。
多个synchronized(this)代码块并发执行
当一个线程访问类中的synchronized(this)的代码块时,该类中的其他synchronized(this)同步代码处于阻塞状态,例如:class SynchronizedThis两个synchronized(this)同步代码块 public class SynchronizedThis { public void methodA(){ synchronized(this){ System.out.println("this A start:"+Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("this A end:"+Thread.currentThread().getName()); } } public void methodB(){ synchronized(this){ System.out.println("this B start:"+Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("this B end:"+Thread.currentThread().getName()); } } }
两个线程类
public class MyThreadA implements Runnable { private SynchronizedThis sthis; public MyThreadA(SynchronizedThis sthis){ this.sthis = sthis; } @Override public void run() { sthis.methodA(); } } public class MyThreadB implements Runnable { private SynchronizedThis sthis; public MyThreadB(SynchronizedThis sthis){ this.sthis = sthis; } @Override public void run() { sthis.methodB(); } }
启动线程类
public class MainThread { public static void main(String[] args) { SynchronizedThis sthis = new SynchronizedThis(); MyThreadA threadA = new MyThreadA(sthis); Thread TA = new Thread(threadA,"A"); TA.start(); MyThreadB threadB = new MyThreadB(sthis); Thread TB = new Thread(threadB,"B"); TB.start(); } }
运行结果,ThreadA运行完成之后ThreadB才能继续执行
this A start:A this A end:A this B start:B this B end:B
synchronized(this)代码块与synchronized方法并发执行
当一个线程访问类中的synchronized(this)的代码块时,该类中的其他synchronized方法处于阻塞状态,例如:class SynchronizedThis一个synchronized(this)同步代码块一个synchronized方法
public class SynchronizedThis { public synchronized void methodA(){ System.out.println("this A start:"+Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("this A end:"+Thread.currentThread().getName()); } public void methodB(){ synchronized(this){ System.out.println("this B start:"+Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("this B end:"+Thread.currentThread().getName()); } } }
两个线程类和启动线程类同上
运行结果,线程A运行完成之后线程B才可以运行
this A start:A this A end:A this B start:B this B end:B
synchronized(this)代码块与非synchronized方法并发执行
synchronized(this)代码块与非同步方法之间是不存在锁竞争的,可以并发执行,例如:public class SynchronizedThis { public void methodA(){ System.out.println("this A start:"+Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("this A end:"+Thread.currentThread().getName()); } public void methodB(){ synchronized(this){ for(int i=0;i<5;i++){ System.out.println("this B start:"+Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("this B end:"+Thread.currentThread().getName()); } } } }
两个线程类和启动线程类同上
运行结果,线程A和线程B并发一起执行了
this A start:A this B start:B0 this A end:A this B end:B0 this B start:B1 this B end:B1 this B start:B2 this B end:B2 this B start:B3 this B end:B3 this B start:B4 this B end:B4
多个synchronized(任意对象)之间并发执行
public class SynchronizedThis { private String flag = new String(); public void method(String name){ synchronized(flag){ for(int i=0;i<5;i++){ System.out.println("this "+name+" start:"+Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("this "+name+" end:"+Thread.currentThread().getName()); } } } }
两个线程类
public class MyThreadA implements Runnable { private SynchronizedThis sthis; public MyThreadA(SynchronizedThis sthis){ this.sthis = sthis; } @Override public void run() { sthis.method("sunwukong"); } } public class MyThreadB implements Runnable { private SynchronizedThis sthis; public MyThreadB(SynchronizedThis sthis){ this.sthis = sthis; } @Override public void run() { sthis.method("zhubajie"); } }
启动线程类
同一个SynchronizedThis
public class MainThread { public static void main(String[] args) { SynchronizedThis sthis = new SynchronizedThis(); MyThreadA threadA = new MyThreadA(sthis); Thread TA = new Thread(threadA,"A"); TA.start(); MyThreadB threadB = new MyThreadB(sthis); Thread TB = new Thread(threadB,"B"); TB.start(); } }
运行结果,线程B需要等待线程A运行完成之后才执行
this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A this zhubajie start:B this zhubajie end:B this zhubajie start:B this zhubajie end:B this zhubajie start:B this zhubajie end:B this zhubajie start:B this zhubajie end:B this zhubajie start:B this zhubajie end:B
多个SynchronizedThis
public class MainThread { public static void main(String[] args) { SynchronizedThis sthis = new SynchronizedThis(); MyThreadA threadA = new MyThreadA(sthis); Thread TA = new Thread(threadA,"A"); TA.start(); SynchronizedThis sthis2 = new SynchronizedThis(); MyThreadB threadB = new MyThreadB(sthis2); Thread TB = new Thread(threadB,"B"); TB.start(); } }
运行结果,由于锁定的对象不是同一个所以可以并发执行,不会阻塞,
this sunwukong start:A this zhubajie start:B this zhubajie end:B this sunwukong end:A this zhubajie start:B this sunwukong start:A this sunwukong end:A this zhubajie end:B this zhubajie start:B this sunwukong start:A this zhubajie end:B this sunwukong end:A this zhubajie start:B this sunwukong start:A this zhubajie end:B this sunwukong end:A this zhubajie start:B this sunwukong start:A this zhubajie end:B this sunwukong end:A
这边需要注意的是如果synchronized(字符常量),无论new多少个对象都会阻塞不会并发执行,因为JVM维护了一个String,Integer等常量池,new新的对象他不会创建新的字符串,而是引用字符串常量池中已经存在的字符串。
注:synchronized(obj)obj不能是基本数据类型,可以包装数据类型
例如:
public class SynchronizedThis {
private String flag = "flag";
public void method(String name){
synchronized(flag){
for(int i=0;i<5;i++){
System.out.println("this "+name+" start:"+Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("this "+name+" end:"+Thread.currentThread().getName());
}
}
}
}
public class MainThread { public static void main(String[] args) { SynchronizedThis sthis = new SynchronizedThis(); MyThreadA threadA = new MyThreadA(sthis); Thread TA = new Thread(threadA,"A"); TA.start(); SynchronizedThis sthis2 = new SynchronizedThis(); MyThreadB threadB = new MyThreadB(sthis2); Thread TB = new Thread(threadB,"B"); TB.start(); } }
运行结果
this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A this zhubajie start:B this zhubajie end:B this zhubajie start:B this zhubajie end:B this zhubajie start:B this zhubajie end:B this zhubajie start:B this zhubajie end:B this zhubajie start:B this zhubajie end:B
上面的private String flag = new String();是个全局变量,如果我们改成局部变量,即使我们只new一个对象,也会并发执行,因为JVM会为每个线程分配一个私有的空间,TheadA和TheadB两个线程锁定的不是同一个flag,下面让我们来验证下:
public class SynchronizedThis { public void method(String name){ String flag = new String(); synchronized(flag){ for(int i=0;i<5;i++){ System.out.println("this "+name+" start:"+Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("this "+name+" end:"+Thread.currentThread().getName()); } } } }
线程类同上,直接看启动线程类
public class MainThread { public static void main(String[] args) { SynchronizedThis sthis = new SynchronizedThis(); MyThreadA threadA = new MyThreadA(sthis); Thread TA = new Thread(threadA,"A"); TA.start(); MyThreadB threadB = new MyThreadB(sthis); Thread TB = new Thread(threadB,"B"); TB.start(); } }
运行结果,A和B并发执行了
this sunwukong start:A this zhubajie start:B this zhubajie end:B this sunwukong end:A this zhubajie start:B this sunwukong start:A this sunwukong end:A this zhubajie end:B this sunwukong start:A this zhubajie start:B this zhubajie end:B this sunwukong end:A this zhubajie start:B this sunwukong start:A this sunwukong end:A this zhubajie end:B this zhubajie start:B this sunwukong start:A this zhubajie end:B this sunwukong end:A
synchronized(任意对象)与synchronized方法之间
public class SynchronizedThis { private Integer flag = new Integer(0); public void method(String name){ synchronized(flag){ for(int i=0;i<5;i++){ System.out.println("this "+name+" start:"+Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("this "+name+" end:"+Thread.currentThread().getName()); } } } public synchronized void method2(String name){ System.out.println("this"+name+" start:"+Thread.currentThread().getName()); System.out.println("this"+name+" end:"+Thread.currentThread().getName()); } }
两个线程类:
public class MyThreadA implements Runnable { private SynchronizedThis sthis; public MyThreadA(SynchronizedThis sthis){ this.sthis = sthis; } @Override public void run() { sthis.method("sunwukong"); } } public class MyThreadB implements Runnable { private SynchronizedThis sthis; public MyThreadB(SynchronizedThis sthis){ this.sthis = sthis; } @Override public void run() { sthis.method2("zhubajie"); } }
启动线程类
public class MainThread { public static void main(String[] args) { SynchronizedThis sthis = new SynchronizedThis(); MyThreadA threadA = new MyThreadA(sthis); Thread TA = new Thread(threadA,"A"); TA.start(); MyThreadB threadB = new MyThreadB(sthis); Thread TB = new Thread(threadB,"B"); TB.start(); } }
运行结果,线程A和线程B可以并发异步执行,因为他们锁的对象不是一个,一个是flag,一个是当前实例this
this sunwukong start:A thiszhubajie start:B thiszhubajie end:B this sunwukong end:A this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A
多个synchronized方法之间
public class SynchronizedThis { public synchronized void method(String name){ for(int i=0;i<5;i++){ System.out.println("this "+name+" start:"+Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("this "+name+" end:"+Thread.currentThread().getName()); } } public synchronized void method2(String name){ System.out.println("this"+name+" start:"+Thread.currentThread().getName()); System.out.println("this"+name+" end:"+Thread.currentThread().getName()); } }
两个线程类,线程启动类同上
运行结果,线程B需要等待线程A执行完成之后再执行,这是因为synchronized方法和synchronized(this)效果一样,都是锁定当前this
this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A thiszhubajie start:B thiszhubajie end:B
synchronized方法与synchronized(*.class)
public class SynchronizedThis { public void method(String name){ synchronized(SynchronizedThis.class){ for(int i=0;i<5;i++){ System.out.println("this "+name+" start:"+Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("this "+name+" end:"+Thread.currentThread().getName()); } } } public synchronized void method2(String name){ System.out.println("this"+name+" start:"+Thread.currentThread().getName()); System.out.println("this"+name+" end:"+Thread.currentThread().getName()); } }
两个线程类
public class MyThreadA implements Runnable { private SynchronizedThis sthis; public MyThreadA(SynchronizedThis sthis){ this.sthis = sthis; } @Override public void run() { sthis.method("sunwukong"); } } public class MyThreadB implements Runnable { private SynchronizedThis sthis; public MyThreadB(SynchronizedThis sthis){ this.sthis = sthis; } @Override public void run() { sthis.method2("zhubajie"); } }
线程启动类
public class MainThread { public static void main(String[] args) { SynchronizedThis sthis = new SynchronizedThis(); MyThreadA threadA = new MyThreadA(sthis); Thread TA = new Thread(threadA,"A"); TA.start(); MyThreadB threadB = new MyThreadB(sthis); Thread TB = new Thread(threadB,"B"); TB.start(); } }
运行结果,线程A和线程B可以并发异步执行,他们一个锁的是this一个当前对象class
this sunwukong start:A thiszhubajie start:B thiszhubajie end:B this sunwukong end:A this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A
静态synchronized方法与synchronized(*.class)
public class SynchronizedThis { public void method(String name){ synchronized(SynchronizedThis.class){ for(int i=0;i<5;i++){ System.out.println("this "+name+" start:"+Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("this "+name+" end:"+Thread.currentThread().getName()); } } } public static synchronized void method2(String name){ System.out.println("this"+name+" start:"+Thread.currentThread().getName()); System.out.println("this"+name+" end:"+Thread.currentThread().getName()); } }
两个线程类和线程启动类同上
运行结果,线程B需要等待线程A运行完成之后才能运行,因为静态静态方法添加synchronized之后锁定的是当前类.class
this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A thiszhubajie start:B thiszhubajie end:B
synchronized(*.class)之间并发执行
public class SynchronizedThis { public void method(String name){ synchronized(SynchronizedThis.class){ for(int i=0;i<5;i++){ System.out.println("this "+name+" start:"+Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("this "+name+" end:"+Thread.currentThread().getName()); } } } public static synchronized void method2(String name){ synchronized(SynchronizedThis.class){ for(int i=0;i<5;i++){ System.out.println("this "+name+" start:"+Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("this "+name+" end:"+Thread.currentThread().getName()); } } } }
线程启动类,我new一个对象
public class MainThread { public static void main(String[] args) { SynchronizedThis sthis = new SynchronizedThis(); MyThreadA threadA = new MyThreadA(sthis); Thread TA = new Thread(threadA,"A"); TA.start(); MyThreadB threadB = new MyThreadB(sthis); Thread TB = new Thread(threadB,"B"); TB.start(); } }
运行结果,线程B需要等待线程A执行完之后才能执行
this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A this zhubajie start:B this zhubajie end:B this zhubajie start:B this zhubajie end:B this zhubajie start:B this zhubajie end:B this zhubajie start:B this zhubajie end:B this zhubajie start:B this zhubajie end:B
如果new两个对象
public class MainThread { public static void main(String[] args) { SynchronizedThis sthis = new SynchronizedThis(); MyThreadA threadA = new MyThreadA(sthis); Thread TA = new Thread(threadA,"A"); TA.start(); SynchronizedThis sthis2 = new SynchronizedThis(); MyThreadB threadB = new MyThreadB(sthis2); Thread TB = new Thread(threadB,"B"); TB.start(); } }
运行结果,和new一个对象效果一样,说明synchronized(SynchronizedThis.class)是对JVM中所有对象实例加锁,后面我再写一篇文章介绍下synchronized在JVM中是怎么工作的
this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A this sunwukong start:A this sunwukong end:A this zhubajie start:B this zhubajie end:B this zhubajie start:B this zhubajie end:B this zhubajie start:B this zhubajie end:B this zhubajie start:B this zhubajie end:B this zhubajie start:B this zhubajie end:B
总结(这里的同一个对象是指我上面的SynchronizedThis sthis = new SynchronizedThis();new了一个还是两个):
1、多个synchronized(this)
同一个对象:不能并发执行,不同对象:可以并发
2、synchronized(this)代码块与synchronized方法
同一个对象::两个加锁效果一样,不能并发执行;不同对象:可以并发
3、synchronized(任意对象)与synchronized方法
同一个对象:可以并发,不同对象:可以并发
4、多个synchronized方法
同一个对象:不能并发执行,不同对象:可以并发
5、synchronized方法与synchronized(*.class)
同一个对象:可以并发,不同对象:可以并发
6、静态synchronized方法与synchronized(*.class)
同一个对象:不能并发执行,不同对象:不能并发执行
7、synchronized(*.class)之间
同一个对象:不能并发执行,不同对象:不能并发执行
下篇文章我会对synchronized在JVM中怎么工作的进行详细讲解。
相关文章推荐
- java中synchronized用法详解
- Java中synchronized关键字修饰方法同步的用法详解
- java中synchronized的用法详解
- Java 中 synchronized的用法详解(四种用法)
- java中synchronized的用法详解
- java中synchronized的用法详解
- synchronized的用法详解
- Synchronized用法详解
- java中synchronized的用法详解
- java中synchronized的用法详解
- java中synchronized的用法与详解
- java线程之synchronized的用法详解
- java中synchronized的用法详解
- java中synchronized的用法详解
- Java 中 synchronized的用法详解(四种用法)
- java中synchronized的用法详解
- java中synchronized的用法详解
- Java 中 synchronized的用法详解(四种用法)
- java中synchronized的用法详解
- java中synchronized的用法详解